Bytes constants

This commit is contained in:
Johan B.W. de Vries 2023-04-10 16:24:29 +02:00
parent a044e3ef0c
commit 959b643542
5 changed files with 71 additions and 16 deletions

View File

@ -233,7 +233,13 @@ def expression(wgn: WasmGenerator, inp: ourlang.Expression) -> None:
wgn.f64.const(inp.value)
return
raise NotImplementedError(f'Constants with type {inp.type3}')
raise NotImplementedError(f'Constants with type {inp.type3:s}')
if isinstance(inp, ourlang.ConstantBytes):
assert inp.data_block is not None, 'Bytes must be memory stored'
assert inp.data_block.address is not None, 'Value not allocated'
wgn.i32.const(inp.data_block.address)
return
if isinstance(inp, ourlang.VariableReference):
if isinstance(inp.variable, ourlang.FunctionParam):
@ -243,6 +249,12 @@ def expression(wgn: WasmGenerator, inp: ourlang.Expression) -> None:
if isinstance(inp.variable, ourlang.ModuleConstantDef):
assert isinstance(inp.type3, type3types.Type3), type3types.TYPE3_ASSERTION_ERROR
if inp.type3 is type3types.bytes:
assert inp.variable.data_block is not None, 'Bytes must be memory stored'
assert inp.variable.data_block.address is not None, 'Value not allocated'
wgn.i32.const(inp.variable.data_block.address)
return
if isinstance(inp.type3, type3types.StructType3):
assert inp.variable.data_block is not None, 'Structs must be memory stored'
assert inp.variable.data_block.address is not None, 'Value not allocated'
@ -735,6 +747,12 @@ def module_data(inp: ourlang.ModuleData) -> bytes:
data_list.append(module_data_f64(constant.value))
continue
if constant.type3 == type3types.bytes:
assert isinstance(constant.value, bytes)
data_list.append(module_data_u32(len(constant.value)))
data_list.append(constant.value)
continue
raise NotImplementedError(constant, constant.type3, constant.value)
block_data = b''.join(data_list)

View File

@ -47,15 +47,32 @@ class ConstantPrimitive(Constant):
def __repr__(self) -> str:
return f'ConstantPrimitive({repr(self.value)})'
class ConstantBytes(Constant):
"""
A bytes constant value expression within a statement
"""
__slots__ = ('value', 'data_block', )
value: bytes
data_block: 'ModuleDataBlock'
def __init__(self, value: bytes, data_block: 'ModuleDataBlock') -> None:
super().__init__()
self.value = value
self.data_block = data_block
def __repr__(self) -> str:
return f'ConstantBytes({repr(self.value)}, @{repr(self.data_block.address)})'
class ConstantTuple(Constant):
"""
A Tuple constant value expression within a statement
"""
__slots__ = ('value', )
value: List[ConstantPrimitive]
value: List[Union[ConstantPrimitive, ConstantBytes]]
def __init__(self, value: List[ConstantPrimitive]) -> None: # FIXME: Tuple of tuples?
def __init__(self, value: List[Union[ConstantPrimitive, ConstantBytes]]) -> None: # FIXME: Tuple of tuples?
super().__init__()
self.value = value
@ -69,9 +86,9 @@ class ConstantStruct(Constant):
__slots__ = ('struct_name', 'value', )
struct_name: str
value: List[ConstantPrimitive]
value: List[Union[ConstantPrimitive, ConstantBytes]]
def __init__(self, struct_name: str, value: List[ConstantPrimitive]) -> None: # FIXME: Struct of structs?
def __init__(self, struct_name: str, value: List[Union[ConstantPrimitive, ConstantBytes]]) -> None: # FIXME: Struct of structs?
super().__init__()
self.struct_name = struct_name
self.value = value
@ -361,10 +378,10 @@ class ModuleDataBlock:
"""
__slots__ = ('data', 'address', )
data: List[ConstantPrimitive]
data: List[Union[ConstantPrimitive, ConstantBytes]]
address: Optional[int]
def __init__(self, data: List[ConstantPrimitive]) -> None:
def __init__(self, data: List[Union[ConstantPrimitive, ConstantBytes]]) -> None:
self.data = data
self.address = None

View File

@ -16,7 +16,7 @@ from .ourlang import (
Expression,
BinaryOp,
ConstantPrimitive, ConstantTuple, ConstantStruct,
ConstantPrimitive, ConstantBytes, ConstantTuple, ConstantStruct,
TupleInstantiation,
FunctionCall, AccessStructMember, Subscript,
@ -191,12 +191,20 @@ class OurVisitor:
if isinstance(node.value, ast.Constant):
type3 = self.visit_type(module, node.annotation)
value_data = self.visit_Module_Constant(module, node.value)
if isinstance(value_data, ConstantBytes):
data_block = value_data.data_block
else:
data_block = None
return ModuleConstantDef(
node.target.id,
node.lineno,
type3,
self.visit_Module_Constant(module, node.value),
None,
value_data,
data_block,
)
if isinstance(node.value, ast.Tuple):
@ -554,14 +562,20 @@ class OurVisitor:
return Subscript(varref, slice_expr)
def visit_Module_Constant(self, module: Module, node: ast.Constant) -> ConstantPrimitive:
del module
def visit_Module_Constant(self, module: Module, node: ast.Constant) -> Union[ConstantPrimitive, ConstantBytes]:
_not_implemented(node.kind is None, 'Constant.kind')
if isinstance(node.value, (int, float, )):
return ConstantPrimitive(node.value)
if isinstance(node.value, bytes):
data_block = ModuleDataBlock([])
module.data.blocks.append(data_block)
result = ConstantBytes(node.value, data_block)
data_block.data.append(result)
return result
raise NotImplementedError(f'{node.value} as constant')
def visit_type(self, module: Module, node: ast.expr) -> type3types.Type3:

View File

@ -323,12 +323,12 @@ class LiteralFitsConstraint(ConstraintBase):
__slots__ = ('type3', 'literal', )
type3: types.Type3OrPlaceholder
literal: Union[ourlang.ConstantPrimitive, ourlang.ConstantTuple, ourlang.ConstantStruct]
literal: Union[ourlang.ConstantPrimitive, ourlang.ConstantBytes, ourlang.ConstantTuple, ourlang.ConstantStruct]
def __init__(
self,
type3: types.Type3OrPlaceholder,
literal: Union[ourlang.ConstantPrimitive, ourlang.ConstantTuple, ourlang.ConstantStruct],
literal: Union[ourlang.ConstantPrimitive, ourlang.ConstantBytes, ourlang.ConstantTuple, ourlang.ConstantStruct],
comment: Optional[str] = None,
) -> None:
super().__init__(comment=comment)
@ -380,6 +380,12 @@ class LiteralFitsConstraint(ConstraintBase):
return Error('Must be real') # FIXME: Add line information
if self.type3 is types.bytes:
if isinstance(self.literal.value, bytes):
return None
return Error('Must be bytes') # FIXME: Add line information
res: NewConstraintList
if isinstance(self.type3, types.AppliedType3):

View File

@ -25,7 +25,7 @@ def phasm_type3_generate_constraints(inp: ourlang.Module) -> List[ConstraintBase
return [*module(ctx, inp)]
def constant(ctx: Context, inp: ourlang.Constant) -> ConstraintGenerator:
if isinstance(inp, (ourlang.ConstantPrimitive, ourlang.ConstantTuple, ourlang.ConstantStruct)):
if isinstance(inp, (ourlang.ConstantPrimitive, ourlang.ConstantBytes, ourlang.ConstantTuple, ourlang.ConstantStruct)):
yield LiteralFitsConstraint(inp.type3, inp)
return