Converted fractional, fixed integral
This commit is contained in:
parent
e1bfcdeb8f
commit
c3124f4325
@ -39,6 +39,16 @@ INSTANCES = {
|
|||||||
'a=f32': stdlib_types.f32_eq_equals,
|
'a=f32': stdlib_types.f32_eq_equals,
|
||||||
'a=f64': stdlib_types.f64_eq_equals,
|
'a=f64': stdlib_types.f64_eq_equals,
|
||||||
},
|
},
|
||||||
|
type3classes.Fractional.operators['/']: {
|
||||||
|
'a=f32': stdlib_types.f32_fractional_div,
|
||||||
|
'a=f64': stdlib_types.f64_fractional_div,
|
||||||
|
},
|
||||||
|
type3classes.Integral.methods['div']: {
|
||||||
|
'a=u32': stdlib_types.u32_integral_div,
|
||||||
|
'a=u64': stdlib_types.u64_integral_div,
|
||||||
|
'a=i32': stdlib_types.i32_integral_div,
|
||||||
|
'a=i64': stdlib_types.i64_integral_div,
|
||||||
|
},
|
||||||
type3classes.Num.operators['+']: {
|
type3classes.Num.operators['+']: {
|
||||||
'a=u32': stdlib_types.u32_num_add,
|
'a=u32': stdlib_types.u32_num_add,
|
||||||
'a=u64': stdlib_types.u64_num_add,
|
'a=u64': stdlib_types.u64_num_add,
|
||||||
@ -157,7 +167,6 @@ U32_OPERATOR_MAP = {
|
|||||||
'^': 'xor',
|
'^': 'xor',
|
||||||
'|': 'or',
|
'|': 'or',
|
||||||
'&': 'and',
|
'&': 'and',
|
||||||
'/': 'div_u' # Division by zero is a trap and the program will panic
|
|
||||||
}
|
}
|
||||||
|
|
||||||
U64_OPERATOR_MAP = {
|
U64_OPERATOR_MAP = {
|
||||||
@ -170,7 +179,6 @@ U64_OPERATOR_MAP = {
|
|||||||
'^': 'xor',
|
'^': 'xor',
|
||||||
'|': 'or',
|
'|': 'or',
|
||||||
'&': 'and',
|
'&': 'and',
|
||||||
'/': 'div_u' # Division by zero is a trap and the program will panic
|
|
||||||
}
|
}
|
||||||
|
|
||||||
I32_OPERATOR_MAP = {
|
I32_OPERATOR_MAP = {
|
||||||
@ -178,7 +186,6 @@ I32_OPERATOR_MAP = {
|
|||||||
'>': 'gt_s',
|
'>': 'gt_s',
|
||||||
'<=': 'le_s',
|
'<=': 'le_s',
|
||||||
'>=': 'ge_s',
|
'>=': 'ge_s',
|
||||||
'/': 'div_s' # Division by zero is a trap and the program will panic
|
|
||||||
}
|
}
|
||||||
|
|
||||||
I64_OPERATOR_MAP = {
|
I64_OPERATOR_MAP = {
|
||||||
@ -186,15 +193,6 @@ I64_OPERATOR_MAP = {
|
|||||||
'>': 'gt_s',
|
'>': 'gt_s',
|
||||||
'<=': 'le_s',
|
'<=': 'le_s',
|
||||||
'>=': 'ge_s',
|
'>=': 'ge_s',
|
||||||
'/': 'div_s' # Division by zero is a trap and the program will panic
|
|
||||||
}
|
|
||||||
|
|
||||||
F32_OPERATOR_MAP = {
|
|
||||||
'/': 'div' # Division by zero is a trap and the program will panic
|
|
||||||
}
|
|
||||||
|
|
||||||
F64_OPERATOR_MAP = {
|
|
||||||
'/': 'div' # Division by zero is a trap and the program will panic
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def tuple_instantiation(wgn: WasmGenerator, inp: ourlang.TupleInstantiation) -> None:
|
def tuple_instantiation(wgn: WasmGenerator, inp: ourlang.TupleInstantiation) -> None:
|
||||||
@ -397,14 +395,6 @@ def expression(wgn: WasmGenerator, inp: ourlang.Expression) -> None:
|
|||||||
if operator := I64_OPERATOR_MAP.get(inp.operator, None):
|
if operator := I64_OPERATOR_MAP.get(inp.operator, None):
|
||||||
wgn.add_statement(f'i64.{operator}')
|
wgn.add_statement(f'i64.{operator}')
|
||||||
return
|
return
|
||||||
if inp.type3 == type3types.f32:
|
|
||||||
if operator := F32_OPERATOR_MAP.get(inp.operator, None):
|
|
||||||
wgn.add_statement(f'f32.{operator}')
|
|
||||||
return
|
|
||||||
if inp.type3 == type3types.f64:
|
|
||||||
if operator := F64_OPERATOR_MAP.get(inp.operator, None):
|
|
||||||
wgn.add_statement(f'f64.{operator}')
|
|
||||||
return
|
|
||||||
|
|
||||||
raise NotImplementedError(expression, inp.operator, inp.left.type3, inp.right.type3, inp.type3)
|
raise NotImplementedError(expression, inp.operator, inp.left.type3, inp.right.type3, inp.type3)
|
||||||
|
|
||||||
@ -439,6 +429,30 @@ def expression(wgn: WasmGenerator, inp: ourlang.Expression) -> None:
|
|||||||
for arg in inp.arguments:
|
for arg in inp.arguments:
|
||||||
expression(wgn, arg)
|
expression(wgn, arg)
|
||||||
|
|
||||||
|
if isinstance(inp.function, type3classes.Type3ClassMethod):
|
||||||
|
# FIXME: Duplicate code with BinaryOp
|
||||||
|
type_var_map = {}
|
||||||
|
|
||||||
|
for type_var, arg_expr in zip(inp.function.signature, inp.arguments + [inp]):
|
||||||
|
if not isinstance(type_var, type3classes.TypeVariable):
|
||||||
|
# Fixed type, not part of the lookup requirements
|
||||||
|
continue
|
||||||
|
|
||||||
|
assert isinstance(arg_expr.type3, type3types.Type3), type3types.TYPE3_ASSERTION_ERROR
|
||||||
|
type_var_map[type_var] = arg_expr.type3
|
||||||
|
|
||||||
|
instance_key = ','.join(
|
||||||
|
f'{k.letter}={v.name}'
|
||||||
|
for k, v in type_var_map.items()
|
||||||
|
)
|
||||||
|
|
||||||
|
instance = INSTANCES.get(inp.function, {}).get(instance_key, None)
|
||||||
|
if instance is not None:
|
||||||
|
instance(wgn)
|
||||||
|
return
|
||||||
|
|
||||||
|
raise NotImplementedError(inp.function, instance_key)
|
||||||
|
|
||||||
wgn.add_statement('call', '${}'.format(inp.function.name))
|
wgn.add_statement('call', '${}'.format(inp.function.name))
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@ from typing import Dict, Iterable, List, Optional, Union
|
|||||||
|
|
||||||
from typing_extensions import Final
|
from typing_extensions import Final
|
||||||
|
|
||||||
from .type3 import typeclasses as type3classes
|
from .type3 import typeclasses as type3typeclasses
|
||||||
from .type3 import types as type3types
|
from .type3 import types as type3types
|
||||||
from .type3.types import PlaceholderForType, StructType3, Type3, Type3OrPlaceholder
|
from .type3.types import PlaceholderForType, StructType3, Type3, Type3OrPlaceholder
|
||||||
|
|
||||||
@ -150,11 +150,11 @@ class BinaryOp(Expression):
|
|||||||
"""
|
"""
|
||||||
__slots__ = ('operator', 'left', 'right', )
|
__slots__ = ('operator', 'left', 'right', )
|
||||||
|
|
||||||
operator: Union[str, type3classes.Type3ClassMethod]
|
operator: Union[str, type3typeclasses.Type3ClassMethod]
|
||||||
left: Expression
|
left: Expression
|
||||||
right: Expression
|
right: Expression
|
||||||
|
|
||||||
def __init__(self, operator: Union[str, type3classes.Type3ClassMethod], left: Expression, right: Expression) -> None:
|
def __init__(self, operator: Union[str, type3typeclasses.Type3ClassMethod], left: Expression, right: Expression) -> None:
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
self.operator = operator
|
self.operator = operator
|
||||||
@ -170,10 +170,10 @@ class FunctionCall(Expression):
|
|||||||
"""
|
"""
|
||||||
__slots__ = ('function', 'arguments', )
|
__slots__ = ('function', 'arguments', )
|
||||||
|
|
||||||
function: 'Function'
|
function: Union['Function', type3typeclasses.Type3ClassMethod]
|
||||||
arguments: List[Expression]
|
arguments: List[Expression]
|
||||||
|
|
||||||
def __init__(self, function: 'Function') -> None:
|
def __init__(self, function: Union['Function', type3typeclasses.Type3ClassMethod]) -> None:
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
self.function = function
|
self.function = function
|
||||||
|
|||||||
@ -37,9 +37,18 @@ from .type3 import types as type3types
|
|||||||
|
|
||||||
PRELUDE_OPERATORS = {
|
PRELUDE_OPERATORS = {
|
||||||
**type3typeclasses.Eq.operators,
|
**type3typeclasses.Eq.operators,
|
||||||
|
**type3typeclasses.Fractional.operators,
|
||||||
|
**type3typeclasses.Integral.operators,
|
||||||
**type3typeclasses.Num.operators,
|
**type3typeclasses.Num.operators,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PRELUDE_METHODS = {
|
||||||
|
**type3typeclasses.Eq.methods,
|
||||||
|
**type3typeclasses.Fractional.methods,
|
||||||
|
**type3typeclasses.Integral.methods,
|
||||||
|
**type3typeclasses.Num.methods,
|
||||||
|
}
|
||||||
|
|
||||||
def phasm_parse(source: str) -> Module:
|
def phasm_parse(source: str) -> Module:
|
||||||
"""
|
"""
|
||||||
Public method for parsing Phasm code into a Phasm Module
|
Public method for parsing Phasm code into a Phasm Module
|
||||||
@ -465,7 +474,11 @@ class OurVisitor:
|
|||||||
if not isinstance(node.func.ctx, ast.Load):
|
if not isinstance(node.func.ctx, ast.Load):
|
||||||
_raise_static_error(node, 'Must be load context')
|
_raise_static_error(node, 'Must be load context')
|
||||||
|
|
||||||
if node.func.id in module.struct_definitions:
|
func: Union[Function, type3typeclasses.Type3ClassMethod]
|
||||||
|
|
||||||
|
if node.func.id in PRELUDE_METHODS:
|
||||||
|
func = PRELUDE_METHODS[node.func.id]
|
||||||
|
elif node.func.id in module.struct_definitions:
|
||||||
struct_definition = module.struct_definitions[node.func.id]
|
struct_definition = module.struct_definitions[node.func.id]
|
||||||
struct_constructor = StructConstructor(struct_definition.struct_type3)
|
struct_constructor = StructConstructor(struct_definition.struct_type3)
|
||||||
|
|
||||||
@ -524,13 +537,15 @@ class OurVisitor:
|
|||||||
|
|
||||||
func = module.functions[node.func.id]
|
func = module.functions[node.func.id]
|
||||||
|
|
||||||
if len(func.posonlyargs) != len(node.args):
|
exp_arg_count = len(func.posonlyargs) if isinstance(func, Function) else len(func.signature) - 1
|
||||||
_raise_static_error(node, f'Function {node.func.id} requires {len(func.posonlyargs)} arguments but {len(node.args)} are given')
|
|
||||||
|
if exp_arg_count != len(node.args):
|
||||||
|
_raise_static_error(node, f'Function {node.func.id} requires {exp_arg_count} arguments but {len(node.args)} are given')
|
||||||
|
|
||||||
result = FunctionCall(func)
|
result = FunctionCall(func)
|
||||||
result.arguments.extend(
|
result.arguments.extend(
|
||||||
self.visit_Module_FunctionDef_expr(module, function, our_locals, arg_expr)
|
self.visit_Module_FunctionDef_expr(module, function, our_locals, arg_expr)
|
||||||
for arg_expr, param in zip(node.args, func.posonlyargs)
|
for arg_expr in node.args
|
||||||
)
|
)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|||||||
@ -90,6 +90,24 @@ def f32_eq_equals(g: Generator) -> None:
|
|||||||
def f64_eq_equals(g: Generator) -> None:
|
def f64_eq_equals(g: Generator) -> None:
|
||||||
g.add_statement('f64.eq')
|
g.add_statement('f64.eq')
|
||||||
|
|
||||||
|
def f32_fractional_div(g: Generator) -> None:
|
||||||
|
g.add_statement('f32.div')
|
||||||
|
|
||||||
|
def f64_fractional_div(g: Generator) -> None:
|
||||||
|
g.add_statement('f64.div')
|
||||||
|
|
||||||
|
def u32_integral_div(g: Generator) -> None:
|
||||||
|
g.add_statement('i32.div_u')
|
||||||
|
|
||||||
|
def u64_integral_div(g: Generator) -> None:
|
||||||
|
g.add_statement('i64.div_u')
|
||||||
|
|
||||||
|
def i32_integral_div(g: Generator) -> None:
|
||||||
|
g.add_statement('i32.div_s')
|
||||||
|
|
||||||
|
def i64_integral_div(g: Generator) -> None:
|
||||||
|
g.add_statement('i64.div_s')
|
||||||
|
|
||||||
def u32_num_add(g: Generator) -> None:
|
def u32_num_add(g: Generator) -> None:
|
||||||
g.add_statement('i32.add')
|
g.add_statement('i32.add')
|
||||||
|
|
||||||
|
|||||||
@ -95,10 +95,8 @@ def expression(ctx: Context, inp: ourlang.Expression) -> ConstraintGenerator:
|
|||||||
exp_type = type3types.LOOKUP_TABLE[sig_part.name]
|
exp_type = type3types.LOOKUP_TABLE[sig_part.name]
|
||||||
yield SameTypeConstraint(exp_type, arg_expr.type3)
|
yield SameTypeConstraint(exp_type, arg_expr.type3)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
if inp.operator in ('|', '&', '^', ):
|
if inp.operator in ('|', '&', '^', ):
|
||||||
yield from expression(ctx, inp.left)
|
yield from expression(ctx, inp.left)
|
||||||
yield from expression(ctx, inp.right)
|
yield from expression(ctx, inp.right)
|
||||||
@ -117,15 +115,6 @@ def expression(ctx: Context, inp: ourlang.Expression) -> ConstraintGenerator:
|
|||||||
comment=f'({inp.operator}) :: a -> a -> a')
|
comment=f'({inp.operator}) :: a -> a -> a')
|
||||||
return
|
return
|
||||||
|
|
||||||
if inp.operator in ('/', ):
|
|
||||||
yield from expression(ctx, inp.left)
|
|
||||||
yield from expression(ctx, inp.right)
|
|
||||||
|
|
||||||
yield MustImplementTypeClassConstraint('Fractional', inp.left.type3)
|
|
||||||
yield SameTypeConstraint(inp.left.type3, inp.right.type3, inp.type3,
|
|
||||||
comment=f'({inp.operator}) :: a -> a -> a')
|
|
||||||
return
|
|
||||||
|
|
||||||
if inp.operator == '==':
|
if inp.operator == '==':
|
||||||
yield from expression(ctx, inp.left)
|
yield from expression(ctx, inp.left)
|
||||||
yield from expression(ctx, inp.right)
|
yield from expression(ctx, inp.right)
|
||||||
@ -151,6 +140,39 @@ def expression(ctx: Context, inp: ourlang.Expression) -> ConstraintGenerator:
|
|||||||
raise NotImplementedError(expression, inp)
|
raise NotImplementedError(expression, inp)
|
||||||
|
|
||||||
if isinstance(inp, ourlang.FunctionCall):
|
if isinstance(inp, ourlang.FunctionCall):
|
||||||
|
if isinstance(inp.function, type3typeclasses.Type3ClassMethod):
|
||||||
|
# FIXME: Duplicate code with BinaryOp
|
||||||
|
|
||||||
|
type_var_map = {
|
||||||
|
x: type3types.PlaceholderForType([])
|
||||||
|
for x in inp.function.signature
|
||||||
|
if isinstance(x, type3typeclasses.TypeVariable)
|
||||||
|
}
|
||||||
|
|
||||||
|
for call_arg in inp.arguments:
|
||||||
|
yield from expression(ctx, call_arg)
|
||||||
|
|
||||||
|
for type_var in inp.function.type3_class.args:
|
||||||
|
assert type_var in type_var_map # When can this happen?
|
||||||
|
|
||||||
|
yield MustImplementTypeClassConstraint(
|
||||||
|
inp.function.type3_class,
|
||||||
|
type_var_map[type_var],
|
||||||
|
)
|
||||||
|
|
||||||
|
for sig_part, arg_expr in zip(inp.function.signature, inp.arguments + [inp]):
|
||||||
|
if isinstance(sig_part, type3typeclasses.TypeVariable):
|
||||||
|
yield SameTypeConstraint(type_var_map[sig_part], arg_expr.type3)
|
||||||
|
continue
|
||||||
|
|
||||||
|
if isinstance(sig_part, type3typeclasses.TypeReference):
|
||||||
|
# On key error: We probably have to a lot of work to do refactoring
|
||||||
|
# the type lookups
|
||||||
|
exp_type = type3types.LOOKUP_TABLE[sig_part.name]
|
||||||
|
yield SameTypeConstraint(exp_type, arg_expr.type3)
|
||||||
|
continue
|
||||||
|
return
|
||||||
|
|
||||||
yield SameTypeConstraint(inp.function.returns_type3, inp.type3,
|
yield SameTypeConstraint(inp.function.returns_type3, inp.type3,
|
||||||
comment=f'The type of a function call to {inp.function.name} is the same as the type that the function returns')
|
comment=f'The type of a function call to {inp.function.name} is the same as the type that the function returns')
|
||||||
|
|
||||||
|
|||||||
@ -88,6 +88,10 @@ Eq = Type3Class('Eq', ['a'], methods={}, operators={
|
|||||||
'==': 'a -> a -> bool',
|
'==': 'a -> a -> bool',
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Fractional = Type3Class('Fractional', ['a'], methods={}, operators={
|
||||||
|
'/': 'a -> a -> a',
|
||||||
|
})
|
||||||
|
|
||||||
Integral = Type3Class('Eq', ['a'], methods={
|
Integral = Type3Class('Eq', ['a'], methods={
|
||||||
'div': 'a -> a -> a',
|
'div': 'a -> a -> a',
|
||||||
}, operators={})
|
}, operators={})
|
||||||
|
|||||||
@ -6,7 +6,7 @@ constraint generator works with.
|
|||||||
"""
|
"""
|
||||||
from typing import Any, Dict, Iterable, List, Optional, Protocol, Union
|
from typing import Any, Dict, Iterable, List, Optional, Protocol, Union
|
||||||
|
|
||||||
from .typeclasses import Eq, Num, Type3Class
|
from .typeclasses import Eq, Fractional, Integral, Num, Type3Class
|
||||||
|
|
||||||
TYPE3_ASSERTION_ERROR = 'You must call phasm_type3 after calling phasm_parse before you can call any other method'
|
TYPE3_ASSERTION_ERROR = 'You must call phasm_type3 after calling phasm_parse before you can call any other method'
|
||||||
|
|
||||||
@ -242,28 +242,28 @@ The bool type, either True or False
|
|||||||
Suffixes with an underscores, as it's a Python builtin
|
Suffixes with an underscores, as it's a Python builtin
|
||||||
"""
|
"""
|
||||||
|
|
||||||
u8 = PrimitiveType3('u8', [Eq])
|
u8 = PrimitiveType3('u8', [Eq, Integral])
|
||||||
"""
|
"""
|
||||||
The unsigned 8-bit integer type.
|
The unsigned 8-bit integer type.
|
||||||
|
|
||||||
Operations on variables employ modular arithmetic, with modulus 2^8.
|
Operations on variables employ modular arithmetic, with modulus 2^8.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
u32 = PrimitiveType3('u32', [Eq, Num])
|
u32 = PrimitiveType3('u32', [Eq, Integral, Num])
|
||||||
"""
|
"""
|
||||||
The unsigned 32-bit integer type.
|
The unsigned 32-bit integer type.
|
||||||
|
|
||||||
Operations on variables employ modular arithmetic, with modulus 2^32.
|
Operations on variables employ modular arithmetic, with modulus 2^32.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
u64 = PrimitiveType3('u64', [Eq, Num])
|
u64 = PrimitiveType3('u64', [Eq, Integral, Num])
|
||||||
"""
|
"""
|
||||||
The unsigned 64-bit integer type.
|
The unsigned 64-bit integer type.
|
||||||
|
|
||||||
Operations on variables employ modular arithmetic, with modulus 2^64.
|
Operations on variables employ modular arithmetic, with modulus 2^64.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
i8 = PrimitiveType3('i8', [Eq])
|
i8 = PrimitiveType3('i8', [Eq, Integral])
|
||||||
"""
|
"""
|
||||||
The signed 8-bit integer type.
|
The signed 8-bit integer type.
|
||||||
|
|
||||||
@ -271,7 +271,7 @@ Operations on variables employ modular arithmetic, with modulus 2^8, but
|
|||||||
with the middel point being 0.
|
with the middel point being 0.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
i32 = PrimitiveType3('i32', [Eq, Num])
|
i32 = PrimitiveType3('i32', [Eq, Integral, Num])
|
||||||
"""
|
"""
|
||||||
The unsigned 32-bit integer type.
|
The unsigned 32-bit integer type.
|
||||||
|
|
||||||
@ -279,7 +279,7 @@ Operations on variables employ modular arithmetic, with modulus 2^32, but
|
|||||||
with the middel point being 0.
|
with the middel point being 0.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
i64 = PrimitiveType3('i64', [Eq, Num])
|
i64 = PrimitiveType3('i64', [Eq, Integral, Num])
|
||||||
"""
|
"""
|
||||||
The unsigned 64-bit integer type.
|
The unsigned 64-bit integer type.
|
||||||
|
|
||||||
@ -287,12 +287,12 @@ Operations on variables employ modular arithmetic, with modulus 2^64, but
|
|||||||
with the middel point being 0.
|
with the middel point being 0.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
f32 = PrimitiveType3('f32', [Eq, Num])
|
f32 = PrimitiveType3('f32', [Eq, Fractional, Num])
|
||||||
"""
|
"""
|
||||||
A 32-bits IEEE 754 float, of 32 bits width.
|
A 32-bits IEEE 754 float, of 32 bits width.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
f64 = PrimitiveType3('f64', [Eq, Num])
|
f64 = PrimitiveType3('f64', [Eq, Fractional, Num])
|
||||||
"""
|
"""
|
||||||
A 32-bits IEEE 754 float, of 64 bits width.
|
A 32-bits IEEE 754 float, of 64 bits width.
|
||||||
"""
|
"""
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user