Support negative literals
This commit is contained in:
parent
ddc0bbdf30
commit
8fa2e4830e
@ -39,11 +39,39 @@ def phasm_parse(source: str) -> Module:
|
||||
"""
|
||||
res = ast.parse(source, '')
|
||||
|
||||
res = OptimizerTransformer().visit(res)
|
||||
|
||||
our_visitor = OurVisitor()
|
||||
return our_visitor.visit_Module(res)
|
||||
|
||||
OurLocals = Dict[str, Union[FunctionParam]] # FIXME: Does it become easier if we add ModuleConstantDef to this dict?
|
||||
|
||||
class OptimizerTransformer(ast.NodeTransformer):
|
||||
"""
|
||||
This class optimizes the Python AST, to prepare it for parsing
|
||||
by the OurVisitor class below.
|
||||
"""
|
||||
def visit_UnaryOp(self, node: ast.UnaryOp) -> Union[ast.UnaryOp, ast.Constant]:
|
||||
"""
|
||||
UnaryOp optimizations
|
||||
|
||||
In the given example:
|
||||
```py
|
||||
x = -4
|
||||
```
|
||||
Python will parse it as a unary minus operation on the constant four.
|
||||
For Phasm purposes, this counts as a literal -4.
|
||||
"""
|
||||
if (
|
||||
isinstance(node.op, (ast.UAdd, ast.USub, ))
|
||||
and isinstance(node.operand, ast.Constant)
|
||||
and isinstance(node.operand.value, (int, float, ))
|
||||
):
|
||||
if isinstance(node.op, ast.USub):
|
||||
node.operand.value = -node.operand.value
|
||||
return node.operand
|
||||
return node
|
||||
|
||||
class OurVisitor:
|
||||
"""
|
||||
Class to visit a Python syntax tree and create an ourlang syntax tree
|
||||
@ -52,6 +80,9 @@ class OurVisitor:
|
||||
|
||||
At some point, we may deviate from Python syntax. If nothing else,
|
||||
we probably won't keep up with the Python syntax changes.
|
||||
|
||||
See OptimizerTransformer for the changes we make after the Python
|
||||
parsing is done but before the phasm parsing is done.
|
||||
"""
|
||||
|
||||
# pylint: disable=C0103,C0116,C0301,R0201,R0912
|
||||
|
||||
@ -45,7 +45,7 @@ class Generator_i32i64:
|
||||
self.store = functools.partial(self.generator.add_statement, f'{prefix}.store')
|
||||
|
||||
def const(self, value: int, comment: Optional[str] = None) -> None:
|
||||
self.generator.add_statement(f'{self.prefix}.const', f'0x{value:08x}', comment=comment)
|
||||
self.generator.add_statement(f'{self.prefix}.const', f'{value}', comment=comment)
|
||||
|
||||
class Generator_i32(Generator_i32i64):
|
||||
def __init__(self, generator: 'Generator') -> None:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
{
|
||||
"TYPE_NAME": "tuple_all_primitives",
|
||||
"TYPE": "(u8, u32, u64, i8, i32, i64, f32, f64, bytes, )",
|
||||
"VAL0": "(1, 4, 8, 1, 4, 8, 125.125, 5000.5, b'Hello, world!', )"
|
||||
"TYPE": "(u8, u32, u64, i8, i8, i32, i32, i64, i64, f32, f32, f64, f64, bytes, )",
|
||||
"VAL0": "(1, 4, 8, 1, -1, 4, -4, 8, -8, 125.125, -125.125, 5000.5, -5000.5, b'Hello, world!', )"
|
||||
}
|
||||
|
||||
@ -267,32 +267,6 @@ def testEntry() -> {type_}:
|
||||
assert 5 == result.returned_value
|
||||
assert TYPE_MAP[type_] == type(result.returned_value)
|
||||
|
||||
@pytest.mark.integration_test
|
||||
@pytest.mark.skip('TODO')
|
||||
def test_explicit_positive_number():
|
||||
code_py = """
|
||||
@exported
|
||||
def testEntry() -> i32:
|
||||
return +523
|
||||
"""
|
||||
|
||||
result = Suite(code_py).run_code()
|
||||
|
||||
assert 523 == result.returned_value
|
||||
|
||||
@pytest.mark.integration_test
|
||||
@pytest.mark.skip('TODO')
|
||||
def test_explicit_negative_number():
|
||||
code_py = """
|
||||
@exported
|
||||
def testEntry() -> i32:
|
||||
return -19
|
||||
"""
|
||||
|
||||
result = Suite(code_py).run_code()
|
||||
|
||||
assert -19 == result.returned_value
|
||||
|
||||
@pytest.mark.integration_test
|
||||
def test_call_pre_defined():
|
||||
code_py = """
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user