def declare_assign(self, children) -> List[Command]: type, identifier, expr = children ident = identifier.ident if ident in self.symbol_table: raise CompileError("Identifier {} already declared".format(ident)) if expr.type != type: raise CompileError( "Identifier {} has been declared as {}, but assigned as {}". format(ident, type, expr.type)) expr_with_ident = Expression(expr.type, expr.value, ident) self.symbol_table.store(ident, expr_with_ident) return []
def assign_ident(self, children) -> List[Command]: identifier, expr = children ident = identifier.ident if ident not in self.symbol_table: raise CompileError( "Identifier {} has not been declared".format(ident)) assigned_type = expr.type declared_type = self.symbol_table.get_expression(ident).type if assigned_type != declared_type: raise CompileError( "Identifier {} has been declared as {}, but assigned as {}". format(ident, declared_type, assigned_type)) self.symbol_table.update(ident, expr.value) return []
def list_elem(self, children) -> ListElem: expr1, expr2 = children if not isinstance(expr1.type, ListType): raise CompileError( "Expression {} has type {} is not a list".format( expr1, expr1.type)) if expr2.type != Type.int(): raise CompileError( "Expression {} should have type int, but is {}".format( expr2, expr2.type)) if expr2.value >= len(expr1.value): raise CompileError( "List {} has length {}, but has been assessed with out-of-range index {}" .format(expr1.ident, len(expr1.value), expr2.value)) return ListElem(expr1.ident, expr1, expr2.value)
def rotate_right(self, children) -> List[Command]: expr, = children if expr.type != Type.int() and expr.type != Type.decimal(): raise CompileError( "Expression {} should have type int or decimal, but is {}". format(expr.value, expr.type)) return [Command.rotate_right(radians(expr.value))]
def backward(self, children) -> List[Command]: expr, = children if expr.type != Type.int() and expr.type != Type.decimal(): raise CompileError( "Expression {} should have type int or decimal, but is {}". format(expr.value, expr.type)) return [Command.backward(expr.value)]
def vector_z(self, children) -> VectorElem: expr, = children if expr.type != Type.vector(): raise CompileError( "Expression {} should have type vector, but is {}".format( expr, expr.type)) return VectorElem(expr.ident, expr, 2)
def declare(self, children) -> List[Command]: type, identifier = children ident = identifier.ident if ident in self.symbol_table: raise CompileError("Identifier {} already declared".format(ident)) self.symbol_table.store( ident, Expression(type, type.default_value, ident=ident)) return []
def vector(self, children) -> Expression: expr1, expr2, expr3 = children for expr in [expr1, expr2, expr3]: if expr.type != Type.decimal(): raise CompileError( "Expression {} should have type decimal, but is {}".format( expr, expr.type)) return Expression(Type.vector(), [expr1.value, expr2.value, expr3.value])
def list(self, children) -> Expression: exprs = children if len(exprs) == 0: return Expression(Type.empty_list(), []) if not all(e.type == exprs[0].type for e in exprs): raise CompileError( "Elements in list {} should have the same type".format(exprs)) return Expression(Type.list_of(exprs[0].type), [e.value for e in exprs])
def repeat(self, children) -> List[Command]: expr = children[0] commands = children[1:] if expr.type != Type.int(): raise CompileError( "Expression {} should have type int, but is {}".format( expr.value, expr.type)) times = expr.value return commands * times
def expr(self, children) -> Expression: child, = children assert isinstance(child, AbstractExpression) if isinstance(child, Identifier) and child.ident not in self.symbol_table: # child.expression is None iff child.ident not in self.symbol_table raise CompileError("Identifier {} has not been declared".format( child.ident)) expr = child.to_expression() assert expr is not None and isinstance(expr, Expression) return expr
def assign_vector_elem(self, children) -> List[Command]: vector_elem, expr = children ident = vector_elem.ident vector = vector_elem.container index = vector_elem.index if expr.type != Type.decimal(): raise CompileError( "Assigned value {} should have type decimal, but is {}".format( expr.value, expr.type)) self._update_nested_ident(ident, expr, index) return []
def assign_list_elem(self, children) -> List[Command]: list_elem, expr = children ident = list_elem.ident list = list_elem.container index = list_elem.index assigned_type = expr.type declared_type = list.type.elem_type if assigned_type != declared_type: raise CompileError( "Assigned value {} should have type {}, but is {}".format( expr.value, declared_type, assigned_type)) self._update_nested_ident(ident, expr, index) return []