Ideas for the IO Monad
This commit is contained in:
parent
0aa8207987
commit
1fb52d1479
@ -84,6 +84,10 @@ def type3(inp: type3types.Type3OrPlaceholder) -> wasm.WasmType:
|
|||||||
# Tuples are passed as pointer, which are i32
|
# Tuples are passed as pointer, which are i32
|
||||||
return wasm.WasmTypeInt32()
|
return wasm.WasmTypeInt32()
|
||||||
|
|
||||||
|
if inp.base == type3types.IO:
|
||||||
|
assert 1 == len(inp.args)
|
||||||
|
return type3(inp.args[0])
|
||||||
|
|
||||||
raise NotImplementedError(type3, inp)
|
raise NotImplementedError(type3, inp)
|
||||||
|
|
||||||
# Operators that work for i32, i64, f32, f64
|
# Operators that work for i32, i64, f32, f64
|
||||||
@ -569,6 +573,12 @@ def statement_if(wgn: WasmGenerator, inp: ourlang.StatementIf) -> None:
|
|||||||
# for stat in inp.else_statements:
|
# for stat in inp.else_statements:
|
||||||
# statement(wgn, stat)
|
# statement(wgn, stat)
|
||||||
|
|
||||||
|
def statement_expression(wgn: WasmGenerator, inp: ourlang.StatementExpression) -> None:
|
||||||
|
"""
|
||||||
|
Compile: Expression whose result is ignored
|
||||||
|
"""
|
||||||
|
expression(wgn, inp.expr)
|
||||||
|
|
||||||
def statement(wgn: WasmGenerator, inp: ourlang.Statement) -> None:
|
def statement(wgn: WasmGenerator, inp: ourlang.Statement) -> None:
|
||||||
"""
|
"""
|
||||||
Compile: any statement
|
Compile: any statement
|
||||||
@ -584,6 +594,10 @@ def statement(wgn: WasmGenerator, inp: ourlang.Statement) -> None:
|
|||||||
if isinstance(inp, ourlang.StatementPass):
|
if isinstance(inp, ourlang.StatementPass):
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if isinstance(inp, ourlang.StatementExpression):
|
||||||
|
statement_expression(wgn, inp)
|
||||||
|
return
|
||||||
|
|
||||||
raise NotImplementedError(statement, inp)
|
raise NotImplementedError(statement, inp)
|
||||||
|
|
||||||
def function_argument(inp: ourlang.FunctionParam) -> wasm.Param:
|
def function_argument(inp: ourlang.FunctionParam) -> wasm.Param:
|
||||||
|
|||||||
@ -270,6 +270,19 @@ class StatementIf(Statement):
|
|||||||
self.statements = []
|
self.statements = []
|
||||||
self.else_statements = []
|
self.else_statements = []
|
||||||
|
|
||||||
|
class StatementExpression(Statement):
|
||||||
|
"""
|
||||||
|
An expression within a function
|
||||||
|
|
||||||
|
The result of the expression is by the code.
|
||||||
|
"""
|
||||||
|
__slots__ = ('expr', )
|
||||||
|
|
||||||
|
expr: Expression
|
||||||
|
|
||||||
|
def __init__(self, expr: Expression) -> None:
|
||||||
|
self.expr = expr
|
||||||
|
|
||||||
class FunctionParam:
|
class FunctionParam:
|
||||||
"""
|
"""
|
||||||
A parameter for a Function
|
A parameter for a Function
|
||||||
|
|||||||
@ -27,6 +27,7 @@ from .ourlang import (
|
|||||||
|
|
||||||
Statement,
|
Statement,
|
||||||
StatementIf, StatementPass, StatementReturn,
|
StatementIf, StatementPass, StatementReturn,
|
||||||
|
StatementExpression,
|
||||||
|
|
||||||
FunctionParam,
|
FunctionParam,
|
||||||
ModuleConstantDef,
|
ModuleConstantDef,
|
||||||
@ -343,6 +344,9 @@ class OurVisitor:
|
|||||||
if isinstance(node, ast.Pass):
|
if isinstance(node, ast.Pass):
|
||||||
return StatementPass()
|
return StatementPass()
|
||||||
|
|
||||||
|
if isinstance(node, ast.Expr):
|
||||||
|
return StatementExpression(self.visit_Module_FunctionDef_expr(module, function, our_locals, node.value))
|
||||||
|
|
||||||
raise NotImplementedError(f'{node} as stmt in FunctionDef')
|
raise NotImplementedError(f'{node} as stmt in FunctionDef')
|
||||||
|
|
||||||
def visit_Module_FunctionDef_expr(self, module: Module, function: Function, our_locals: OurLocals, node: ast.expr) -> Expression:
|
def visit_Module_FunctionDef_expr(self, module: Module, function: Function, our_locals: OurLocals, node: ast.expr) -> Expression:
|
||||||
@ -593,6 +597,22 @@ class OurVisitor:
|
|||||||
raise NotImplementedError(f'{node.value} as constant')
|
raise NotImplementedError(f'{node.value} as constant')
|
||||||
|
|
||||||
def visit_type(self, module: Module, node: ast.expr) -> type3types.Type3:
|
def visit_type(self, module: Module, node: ast.expr) -> type3types.Type3:
|
||||||
|
if isinstance(node, ast.Call):
|
||||||
|
if not isinstance(node.func, ast.Name):
|
||||||
|
_raise_static_error(node, 'Can only call Monads by name')
|
||||||
|
|
||||||
|
if node.keywords:
|
||||||
|
_raise_static_error(node, 'Monads cannot have keyword arguments')
|
||||||
|
|
||||||
|
monad_type = self.visit_type(module, node.func)
|
||||||
|
if not isinstance(monad_type, type3types.MonadType3):
|
||||||
|
_raise_static_error(node, 'Must be a Monad')
|
||||||
|
|
||||||
|
return type3types.AppliedType3(
|
||||||
|
monad_type,
|
||||||
|
(self.visit_type(module, x) for x in node.args)
|
||||||
|
)
|
||||||
|
|
||||||
if isinstance(node, ast.Constant):
|
if isinstance(node, ast.Constant):
|
||||||
if node.value is None:
|
if node.value is None:
|
||||||
return type3types.none
|
return type3types.none
|
||||||
|
|||||||
@ -183,6 +183,12 @@ def statement_if(ctx: Context, fun: ourlang.Function, inp: ourlang.StatementIf)
|
|||||||
for stmt in inp.else_statements:
|
for stmt in inp.else_statements:
|
||||||
yield from statement(ctx, fun, stmt)
|
yield from statement(ctx, fun, stmt)
|
||||||
|
|
||||||
|
def statement_expression(ctx: Context, fun: ourlang.Function, inp: ourlang.StatementExpression) -> ConstraintGenerator:
|
||||||
|
yield from expression(ctx, inp.expr)
|
||||||
|
|
||||||
|
yield SameTypeConstraint(fun.returns_type3, inp.expr.type3,
|
||||||
|
comment=f'TODO')
|
||||||
|
|
||||||
def statement(ctx: Context, fun: ourlang.Function, inp: ourlang.Statement) -> ConstraintGenerator:
|
def statement(ctx: Context, fun: ourlang.Function, inp: ourlang.Statement) -> ConstraintGenerator:
|
||||||
if isinstance(inp, ourlang.StatementReturn):
|
if isinstance(inp, ourlang.StatementReturn):
|
||||||
yield from statement_return(ctx, fun, inp)
|
yield from statement_return(ctx, fun, inp)
|
||||||
@ -192,6 +198,10 @@ def statement(ctx: Context, fun: ourlang.Function, inp: ourlang.Statement) -> Co
|
|||||||
yield from statement_if(ctx, fun, inp)
|
yield from statement_if(ctx, fun, inp)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if isinstance(inp, ourlang.StatementExpression):
|
||||||
|
yield from statement_expression(ctx, fun, inp)
|
||||||
|
return
|
||||||
|
|
||||||
raise NotImplementedError(statement, fun, inp)
|
raise NotImplementedError(statement, fun, inp)
|
||||||
|
|
||||||
def function(ctx: Context, inp: ourlang.Function) -> ConstraintGenerator:
|
def function(ctx: Context, inp: ourlang.Function) -> ConstraintGenerator:
|
||||||
|
|||||||
@ -69,6 +69,14 @@ class PrimitiveType3(Type3):
|
|||||||
|
|
||||||
__slots__ = ()
|
__slots__ = ()
|
||||||
|
|
||||||
|
class MonadType3(Type3):
|
||||||
|
"""
|
||||||
|
A type method to indicate that actions have to be made
|
||||||
|
one after the other, usually because they affect outside state.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__slots__ = ()
|
||||||
|
|
||||||
class IntType3(Type3):
|
class IntType3(Type3):
|
||||||
"""
|
"""
|
||||||
Sometimes you can have an int as type, e.g. when using static arrays
|
Sometimes you can have an int as type, e.g. when using static arrays
|
||||||
@ -307,6 +315,8 @@ It should be applied with zero or more arguments. It has a compile time
|
|||||||
determined length, and each argument can be different.
|
determined length, and each argument can be different.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
IO = MonadType3('IO')
|
||||||
|
|
||||||
LOOKUP_TABLE: Dict[str, Type3] = {
|
LOOKUP_TABLE: Dict[str, Type3] = {
|
||||||
'none': none,
|
'none': none,
|
||||||
'bool': bool_,
|
'bool': bool_,
|
||||||
@ -319,4 +329,6 @@ LOOKUP_TABLE: Dict[str, Type3] = {
|
|||||||
'f32': f32,
|
'f32': f32,
|
||||||
'f64': f64,
|
'f64': f64,
|
||||||
'bytes': bytes,
|
'bytes': bytes,
|
||||||
|
|
||||||
|
'IO': IO,
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user