def validate_func_int(expr1, expr2, pos): if expr1.type() != Type.INTEGER or expr2.type() != Type.INTEGER: if expr1.type() == Type.SPRITEGROUP_REF: raise generic.ProcCallSyntaxError(expr1.name, expr1.pos) if expr2.type() == Type.SPRITEGROUP_REF: raise generic.ProcCallSyntaxError(expr2.name, expr2.pos) raise generic.ScriptError( "Binary operator requires both operands to be integers.", pos)
def reduce(self, id_dicts=None, unknown_id_fatal=True): expr = self.expr.reduce(id_dicts) if expr.type() != Type.INTEGER: if expr.type() == Type.SPRITEGROUP_REF: raise generic.ProcCallSyntaxError(expr.name, expr.pos) raise generic.ScriptError( "Not-operator (!) requires an integer argument.", expr.pos) if isinstance(expr, ConstantNumeric): return ConstantNumeric(expr.value == 0) if isinstance(expr, Not): return Boolean(expr.expr).reduce() if isinstance(expr, BinOp): if expr.op == nmlop.CMP_EQ: return nmlop.CMP_NEQ(expr.expr1, expr.expr2) if expr.op == nmlop.CMP_NEQ: return nmlop.CMP_EQ(expr.expr1, expr.expr2) if expr.op == nmlop.CMP_LE: return nmlop.CMP_GT(expr.expr1, expr.expr2) if expr.op == nmlop.CMP_GE: return nmlop.CMP_LT(expr.expr1, expr.expr2) if expr.op == nmlop.CMP_LT: return nmlop.CMP_GE(expr.expr1, expr.expr2) if expr.op == nmlop.CMP_GT: return nmlop.CMP_LE(expr.expr1, expr.expr2) if expr.op == nmlop.HASBIT: return nmlop.NOTHASBIT(expr.expr1, expr.expr2) if expr.op == nmlop.NOTHASBIT: return nmlop.HASBIT(expr.expr1, expr.expr2) return Not(expr)
def reduce(self, id_dicts=None, unknown_id_fatal=True): expr = self.expr.reduce(id_dicts) if expr.type() != Type.INTEGER: if expr.type() == Type.SPRITEGROUP_REF: raise generic.ProcCallSyntaxError(expr.name, expr.pos) raise generic.ScriptError( "Only integers can be converted to a boolean value.", expr.pos) if expr.is_boolean(): return expr return Boolean(expr)
def validate_func_float(expr1, expr2, pos): if expr1.type() not in (Type.INTEGER, Type.FLOAT) or expr2.type() not in (Type.INTEGER, Type.FLOAT): if expr1.type() == Type.SPRITEGROUP_REF: raise generic.ProcCallSyntaxError(expr1.name, expr1.pos) if expr2.type() == Type.SPRITEGROUP_REF: raise generic.ProcCallSyntaxError(expr2.name, expr2.pos) raise generic.ScriptError( "Binary operator requires both operands to be integers or floats.", pos) # If one is a float, the other must be constant since we can't handle floats at runtime if (expr1.type() == Type.FLOAT and not isinstance(expr2, (ConstantNumeric, ConstantFloat))) or ( expr2.type() == Type.FLOAT and not isinstance(expr1, (ConstantNumeric, ConstantFloat))): raise generic.ScriptError( "Floating-point operations are only possible when both operands are compile-time constants.", pos)
def reduce(self, id_dicts=None, unknown_id_fatal=True): expr = self.expr.reduce(id_dicts) if expr.type() != Type.INTEGER: if expr.type() == Type.SPRITEGROUP_REF: raise generic.ProcCallSyntaxError(expr.name, expr.pos) raise generic.ScriptError("abs() requires an integer argument.", expr.pos) if isinstance(expr, ConstantNumeric): if expr.value < 0: return ConstantNumeric(-expr.value) else: return ConstantNumeric(expr.value) return AbsOp(expr, self.pos)
def reduce(self, id_dicts=None, unknown_id_fatal=True): guard = self.guard.reduce(id_dicts) expr1 = self.expr1.reduce(id_dicts) expr2 = self.expr2.reduce(id_dicts) if isinstance(guard, ConstantNumeric): if guard.value != 0: return expr1 else: return expr2 if guard.type() != Type.INTEGER or expr1.type( ) != Type.INTEGER or expr2.type() != Type.INTEGER: if guard.type() == Type.SPRITEGROUP_REF: raise generic.ProcCallSyntaxError(guard.name, guard.pos) if expr1.type() == Type.SPRITEGROUP_REF: raise generic.ProcCallSyntaxError(expr1.name, expr1.pos) if expr2.type() == Type.SPRITEGROUP_REF: raise generic.ProcCallSyntaxError(expr2.name, expr2.pos) raise generic.ScriptError( "All parts of the ternary operator (?:) must be integers.", self.pos) return TernaryOp(guard, expr1, expr2, self.pos)
def reduce(self, id_dicts=None, unknown_id_fatal=True): expr = self.expr.reduce(id_dicts) if expr.type() != Type.INTEGER: if expr.type() == Type.SPRITEGROUP_REF: raise generic.ProcCallSyntaxError(expr.name, expr.pos) raise generic.ScriptError( "Not-operator (~) requires an integer argument.", expr.pos) if isinstance(expr, ConstantNumeric): return ConstantNumeric(0xFFFFFFFF ^ expr.value) if isinstance(expr, BinNot): return expr.expr return BinNot(expr)
def reduce(self, id_dicts=None, unknown_id_fatal=True): args = [] if self.value is not None: value = self.value.reduce(id_dicts) if value.type() != Type.INTEGER: if value.type() == Type.SPRITEGROUP_REF: raise generic.ProcCallSyntaxError(value.name, value.pos) raise generic.ScriptError("Value to store must be an integer.", value.pos) args.append(value) register = self.register.reduce(id_dicts) if register.type() != Type.INTEGER: if register.type() == Type.SPRITEGROUP_REF: raise generic.ProcCallSyntaxError(register.name, register.pos) raise generic.ScriptError("Register to access must be an integer.", register.pos) if isinstance(register, ConstantNumeric) and register.value > self.info["max"]: raise generic.ScriptError( "Maximum register for {} is {:d}".format( self.name, self.info["max"]), self.pos) if isinstance( register, ConstantNumeric) and register.value in self.info["reserved"]: raise generic.ScriptError( "Temporary registers from 128 to 255 are reserved for NML's internal calculations.", self.pos) args.append(register) if self.grfid is not None: grfid = self.grfid.reduce(id_dicts) # Test validity parse_string_to_dword(grfid) args.append(grfid) return StorageOp(self.name, args, self.pos)
def reduce(self, id_dicts=None, unknown_id_fatal=True): ret = ConstantNumeric(0, self.pos) for orig_expr in self.values: val = orig_expr.reduce(id_dicts) if val.type() != Type.INTEGER: if val.type() == Type.SPRITEGROUP_REF: raise generic.ProcCallSyntaxError(val.name, val.pos) raise generic.ScriptError( "Parameters of 'bitmask' must be integers.", orig_expr.pos) if isinstance(val, ConstantNumeric) and val.value >= 32: raise generic.ScriptError( "Parameters of 'bitmask' cannot be greater than 31", orig_expr.pos) val = nmlop.SHIFT_LEFT(1, val) ret = nmlop.OR(ret, val) return ret.reduce()