Commit 101d8867 authored by Tom Niget's avatar Tom Niget

User generics attempt #4

parent 6cd4878c
......@@ -47,3 +47,19 @@ Note: gcc may require the `-fcoroutines` flag.
`cd` into the `trans` directory, set up your `.env` file (you can copy the `.env.example` file), and run `python3 test_runner.py`.
If you're getting include errors, make sure you've cloned the runtime submodule. If you forgot, run `git submodule update --init --recursive`.
## TODO (2023-10-17)
Implement custom protocol definition so that we can define stuff like Iterable and it generates a concept in C++ and a type erased wrapper (like std::function)
If you call a function that takes Iterable => the function is a template so no overhead
Be able to store functions using their real functor type name so no overhead of std::function
If you store a function with no further information it uses our callable type
If you store an object into a protocol type => it uses the protocol type erased wrapper
Implement decorators as template inheriting classes as to allow people to implement their own decorators in the c++ side
Use "static" to store the python interpreter for lazy init of python functions
\ No newline at end of file
# coding: utf-8
Generic: BuiltinFeature["Generic"]
TypeVar: BuiltinFeature["TypeVar"]
\ No newline at end of file
# coding: utf-8
from typing import TypeVar, Generic
from dataclasses import dataclass
T = TypeVar("T")
@dataclass
class Thing():
x: int
if __name__ == "__main__":
a = Thing(1)
\ No newline at end of file
......@@ -166,6 +166,7 @@ class BlockVisitor(NodeVisitor):
def visit_Assign(self, node: ast.Assign) -> Iterable[str]:
if len(node.targets) != 1:
raise NotImplementedError(node)
#if node.value.type
yield from self.visit_lvalue(node.targets[0], node.is_declare)
yield " = "
yield from self.expr().visit(node.value)
......
......@@ -54,7 +54,7 @@ class ScoperBlockVisitor(ScoperVisitor):
self.scope.vars[alias.asname or alias.name] = dataclasses.replace(mod, kind=VarKind.LOCAL)
def visit_ImportFrom(self, node: ast.ImportFrom):
if node.module in {"typing", "__future__"}:
if node.module in {"typing2", "__future__"}:
return
module = self.get_module(node.module)
node.module_obj = module.type
......@@ -151,26 +151,48 @@ class ScoperBlockVisitor(ScoperVisitor):
self.scope.vars[node.name] = VarDecl(VarKind.LOCAL, ftype)
def visit_ClassDef(self, node: ast.ClassDef):
ctype = UserType(node.name)
class NewUserType(UserType):
def __init__(self):
super().__init__(node.name)
#ctype = UserType(node.name)
ctype = NewUserType
cttype = TypeType(ctype)
typevars = []
bases_after = []
for base in node.bases:
if isinstance(base, ast.Subscript):
if isinstance(base.slice, ast.Name):
sliceval = [base.slice.id]
elif isinstance(base.slice, ast.Tuple):
sliceval = [n.id for n in base.slice.elts]
if is_builtin(self.expr().visit(base.slice), "Generic"):
typevars = sliceval
else:
bases_after.append(base)
if not typevars:
cttype.type_object = cttype.type_object()
self.scope.vars[node.name] = VarDecl(VarKind.LOCAL, cttype)
scope = self.scope.child(ScopeKind.CLASS)
scope.obj_type = ctype
scope.obj_type = cttype.type_object
scope.class_ = scope
node.inner_scope = scope
node.type = ctype
node.type = cttype.type_object
visitor = ScoperClassVisitor(scope, cur_class=cttype)
visitor.visit_block(node.body)
for deco in node.decorator_list:
deco = self.expr().visit(deco)
if is_builtin(deco, "dataclass"):
# init_type = FunctionType([cttype, *cttype.members.values()], TypeVariable())
# cttype.methods["__init__"] = init_type
for base in bases_after:
base = self.expr().visit(base)
if is_builtin(base, "Enum"):
cttype.type_object.parents.append(TY_INT)
for k, m in cttype.type_object.fields.items():
m.type = cttype.type_object
m.val = ast.literal_eval(m.val)
assert type(m.val) == int
cttype.type_object.fields["value"] = MemberDef(TY_INT)
lnd = linenodata(node)
init_method = ast.FunctionDef(
name="__init__",
args=ast.arguments(
args=[ast.arg(arg="self"), * [ast.arg(arg=n) for n in ctype.get_members()]],
args=[ast.arg(arg="self"), ast.arg(arg="value")],
defaults=[],
kw_defaults=[],
kwarg=None,
......@@ -179,10 +201,10 @@ class ScoperBlockVisitor(ScoperVisitor):
),
body=[
ast.Assign(
targets=[ast.Attribute(value=ast.Name(id="self"), attr=n)],
value=ast.Name(id=n),
targets=[ast.Attribute(value=ast.Name(id="self"), attr="value")],
value=ast.Name(id="value"),
**lnd
) for n in ctype.get_members()
)
],
decorator_list=[],
returns=None,
......@@ -192,22 +214,19 @@ class ScoperBlockVisitor(ScoperVisitor):
_, rtype = visitor.visit_FunctionDef(init_method)
visitor.visit_function_definition(init_method, rtype)
node.body.append(init_method)
cttype.type_object.is_enum = True
else:
raise NotImplementedError(deco)
for base in node.bases:
base = self.expr().visit(base)
if is_builtin(base, "Enum"):
ctype.parents.append(TY_INT)
for k, m in ctype.fields.items():
m.type = ctype
m.val = ast.literal_eval(m.val)
assert type(m.val) == int
ctype.fields["value"] = MemberDef(TY_INT)
raise NotImplementedError(base)
for deco in node.decorator_list:
deco = self.expr().visit(deco)
if is_builtin(deco, "dataclass"):
# init_type = FunctionType([cttype, *cttype.members.values()], TypeVariable())
# cttype.methods["__init__"] = init_type
lnd = linenodata(node)
init_method = ast.FunctionDef(
name="__init__",
args=ast.arguments(
args=[ast.arg(arg="self"), ast.arg(arg="value")],
args=[ast.arg(arg="self"), * [ast.arg(arg=n) for n in cttype.type_object.get_members()]],
defaults=[],
kw_defaults=[],
kwarg=None,
......@@ -216,10 +235,10 @@ class ScoperBlockVisitor(ScoperVisitor):
),
body=[
ast.Assign(
targets=[ast.Attribute(value=ast.Name(id="self"), attr="value")],
value=ast.Name(id="value"),
targets=[ast.Attribute(value=ast.Name(id="self"), attr=n)],
value=ast.Name(id=n),
**lnd
)
) for n in cttype.type_object.get_members()
],
decorator_list=[],
returns=None,
......@@ -229,9 +248,8 @@ class ScoperBlockVisitor(ScoperVisitor):
_, rtype = visitor.visit_FunctionDef(init_method)
visitor.visit_function_definition(init_method, rtype)
node.body.append(init_method)
ctype.is_enum = True
else:
raise NotImplementedError(base)
raise NotImplementedError(deco)
def visit_If(self, node: ast.If):
scope = self.scope.child(ScopeKind.FUNCTION_INNER)
......
......@@ -4,10 +4,10 @@ import inspect
from typing import List
from transpiler.phases.typing import ScopeKind, VarDecl, VarKind
from transpiler.phases.typing.common import ScoperVisitor, get_iter, get_next
from transpiler.phases.typing.common import ScoperVisitor, get_iter, get_next, is_builtin
from transpiler.phases.typing.types import BaseType, TupleType, TY_STR, TY_BOOL, TY_INT, \
TY_COMPLEX, TY_NONE, FunctionType, PyList, TypeVariable, PySet, TypeType, PyDict, Promise, PromiseKind, UserType, \
TY_SLICE, TY_FLOAT, RuntimeValue
TY_SLICE, TY_FLOAT, RuntimeValue, BuiltinFeature
from transpiler.utils import linenodata
DUNDER = {
......@@ -106,13 +106,11 @@ class ScoperExprVisitor(ScoperVisitor):
def visit_Call(self, node: ast.Call) -> BaseType:
ftype = self.visit(node.func)
if is_builtin(ftype, "TypeVar"):
return TypeType(TypeVariable(*[ast.literal_eval(arg) for arg in node.args]))
if ftype.typevars:
ftype = ftype.gen_sub(None, {v.name: TypeVariable(v.name) for v in ftype.typevars})
from transpiler.exceptions import CompileError
try:
argtypes = [self.visit(arg) for arg in node.args]
except CompileError as e:
pass
rtype = self.visit_function_call(ftype, [self.visit(arg) for arg in node.args])
actual = rtype
node.is_await = False
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment