class NodeStatementReturn: NodeStatement;
class NodeStatementFor: NodeStatement;
class NodeStatementNext: NodeStatement;
+class NodeStatementRead: NodeStatement;
+class NodeStatementRestore: NodeStatement;
+class NodeStatementData: NodeStatement;
class NodeExpression: Node;
class NodeExpressionOr: NodeExpression;
class NodeExpressionAnd: NodeExpression;
pass
class Context:
- def __init__(self, program = None, variables = None, i = 0, j = 1):
+ def __init__(
+ self,
+ program = None,
+ variables = None,
+ i = 0,
+ j = 1,
+ k = 0,
+ l = 1,
+ m = 0
+ ):
self.program = program if program is not None else NodeProgram()
self.variables = variables if variables is not None else {}
+
+ # execute pointer (line index, statement index)
self.i = i
self.j = j
+ # read pointer (line index, statement index, item index)
+ self.k = k
+ self.l = l
+ self.m = m
+
def run(self):
try:
self.execute()
self.j = 1
raise EndException()
- def goto(self, target):
+ def find_line(self, target):
for i in range(len(self.program.children)):
if target == self.program.children[i].children[0].int_value:
- self.i = i
- self.j = 1
- break
- else:
- raise Exception(
- f'?UNDEF\'D STATEMENT ERROR IN {self.line_number():d}'
- )
+ return i
+ raise Exception(
+ f'?UNDEF\'D STATEMENT ERROR IN {self.line_number():d}'
+ )
def factory(tag, *args, **kwargs):
return tag_to_class[tag](*args, **kwargs)
print()
@method(NodeStatementGoto)
def execute(self, context):
- context.goto(self.children[0].int_value)
+ context.i = context.find_line(self.children[0].int_value)
+ context.j = 1
@method(NodeStatementIf)
def execute(self, context):
value = self.children[0].evaluate(context)
def execute(self, context):
i = context.i
j = context.j
- context.goto(self.children[0].int_value)
+ context.i = context.find_line(self.children[0].int_value)
+ context.j = 1
try:
context.execute()
except ReturnException:
@method(NodeStatementNext)
def execute(self, context):
raise NextException()
+@method(NodeStatementRead)
+def execute(self, context):
+ while context.k < len(context.program.children):
+ line = context.program.children[context.k]
+ while context.l < len(line.children):
+ statement = line.children[context.l]
+ if (
+ isinstance(statement, NodeStatementData) and
+ context.m < len(statement.children)
+ ):
+ item = statement.children[context.m]
+ context.m += 1
+ break
+ context.l += 1
+ context.m = 0
+ else:
+ context.k += 1
+ context.l = 1
+ assert context.m == 0
+ continue
+ break
+ else:
+ raise Exception(
+ f'?OUT OF DATA ERROR IN {context.line_number():d}'
+ )
+
+ name = self.children[0].str_value
+ if name[-1] == '$':
+ if not isinstance(item, NodeStrLiteral):
+ raise Exception(
+ f'?TYPE MISMATCH ERROR IN {context.line_number():d}'
+ )
+ value = item.text[0]
+ elif name[-1] == '%':
+ if isinstance(item, NodeTextIntLiteral):
+ value = item.int_value
+ elif isinstance(item, NodeFloatLiteral):
+ value = int(math.floor(item.float_value))
+ else:
+ raise Exception(
+ f'?TYPE MISMATCH ERROR IN {context.line_number():d}'
+ )
+ value = ((value + 0x8000) & 0xffff) - 0x8000
+ else:
+ if isinstance(item, NodeTextIntLiteral):
+ value = float(item.int_value)
+ elif isinstance(item, NodeFloatLiteral):
+ value = item.float_value
+ else:
+ raise Exception(
+ f'?TYPE MISMATCH ERROR IN {context.line_number():d}'
+ )
+ context.variables[name] = value
+@method(NodeStatementRestore)
+def execute(self, context):
+ context.k = (
+ context.find_line(self.children[0].int_value)
+ if len(self.children) >= 1 else
+ 0
+ )
+ context.l = 1
+ context.m = 0
+@method(NodeStatementData)
+def execute(self, context):
+ pass
del execute
@method(NodeExpression)