Files
jarvis-models/runtime/ast/runtime.py
2024-03-21 15:59:35 +08:00

96 lines
3.0 KiB
Python

class Runtime:
def __init__(self, records={}, parent=None):
self.parent = parent
self.records = records
def run(self, ast, records={}):
self.records.update(records)
if ast["type"] == "Program":
return self.program(ast)
def program(self, ast):
return self.block(ast.get("body"))
def block(self, ast):
for statement in ast.get("body"):
s = self.switch(statement)
if s != None:
return s
def switch(self, ast):
t = ast["type"]
if t == "VariableDeclaration":
self.variable_declaration(ast)
if t == "AssignmentExpression":
self.assignment_expression(ast)
if t == "CallExpression":
self.call_function(ast)
if t == "ReturnStatement":
return self.exec_return(ast)
def assignment_expression(self, ast):
id = ast.get("identifier").get("name")
v = ast.get("value")
l = self.literal(v)
self.records[id] = self.unquote(v)
def _is_call_function(self, ast):
return ast["type"] == "CallExpression"
def call_function(self,ast):
id = ast.get("callee").get("name")
args = ast.get("arguments")
unquoted_args = []
for arg in args:
unquoted_args.append(self.unquote(arg))
fu = self.records.get(id)
if fu == None:
raise Exception("Function not found: " + id)
return fu(*unquoted_args)
def unquote(self, ast):
if self._is_identifier(ast):
return self.records.get(ast.get("name"))
if self._is_literal(ast):
return self.literal(ast)
if self._is_call_function(ast):
return self.call_function(ast)
def variable_declaration(self, ast):
id = ast.get("identifier").get("name")
v = ast.get("value")
if self._is_literal(v):
l = self.literal(v)
if l != None:
self.records[id] = l
else:
raise Exception("Unknown literal type: " + v.get("type"))
if self._is_identifier(v):
self.records[id] = self.records.get(v.get("name"))
def literal(self, ast):
if ast.get("type") == "StringLiteral":
return ast.get("value")
elif ast.get("type") == "NumericLiteral":
return int(ast.get("value"))
elif ast.get("type") == "FloatLiteral":
return float(ast.get("value"))
def _is_identifier(self, ast):
return ast["type"] == "Identifier"
def _is_literal(self, ast):
return ast["type"] in ["NumericLiteral", "StringLiteral", "FloatLiteral"]
def exec_return(self, ast):
v = ast.get("value")
if self._is_literal(v):
return self.literal(v)
if self._is_identifier(v):
return self.records.get(v.get("name"))
if self._is_call_function(v):
return self.call_function(v)
def debug_print_records(self):
print(self.records)