def generate_code(self, arg_types: List[uni.InferenceType], code_builder: OpCodeBuilder): assert len(arg_types) == 2, \ f'Error during code generation of \'{self.name}\': ' \ f'expected {self.num_args} arguments but found {len(arg_types)}' t1, t2 = arg_types[0], arg_types[1] assert t1.is_equal(t2) or \ (isinstance(t1, uni.InferenceList) and isinstance(t1.t, uni.InferenceTypeVar) and isinstance(t2, uni.InferenceList) and isinstance(t2.t, uni.InferenceTypeVar)), \ f'Error during code generation: {self.name} expects both arguments to be of the same type' assert not isinstance(t1, uni.InferenceVoid), \ f'Error during code generation: could not generate {self.name} code for type {t1}' arg1 = gen_utils.Local(-2) arg2 = gen_utils.Local(-1) if isinstance(t1, uni.InferenceInt) or isinstance( t1, uni.InferenceChar): code_builder.add(codes.LdLoc(arg1)) code_builder.add(codes.LdLoc(arg2)) code_builder.add(codes.Add()) code_builder.add(codes.Ret()) elif isinstance(t1, uni.InferenceList): null_label_1 = code_builder.fresh_label() null_label_2 = code_builder.fresh_label() code_builder.add(codes.LdLoc(arg1)) code_builder.add(codes.BrFalse(null_label_1)) code_builder.add(codes.LdLoc(arg1)) code_builder.add(codes.LdFld(FieldType.Hd)) code_builder.add(codes.LdLoc(arg1)) code_builder.add(codes.LdFld(FieldType.Tl)) code_builder.add(codes.LdLoc(arg2)) code_builder.add_call(self.name, [t1, t1], hide=True) code_builder.add(codes.CreateListCons()) code_builder.add(codes.Ret()) code_builder.mark(null_label_1) code_builder.add(codes.LdLoc(arg2)) code_builder.add(codes.BrFalse(null_label_2)) if isinstance(t2.t, uni.InferenceTypeVar): code_builder.add_print_str('Error: type var list has contents') code_builder.add(codes.Halt()) code_builder.add(codes.LdLoc(arg2)) code_builder.add(codes.LdFld(FieldType.Hd)) code_builder.add(codes.PushConst(0)) code_builder.add(codes.LdLoc(arg2)) code_builder.add(codes.LdFld(FieldType.Tl)) code_builder.add_call(self.name, [t1, t1], hide=True) code_builder.add(codes.CreateListCons()) code_builder.add(codes.Ret()) code_builder.mark(null_label_2) code_builder.add(codes.CreateListNil()) code_builder.add(codes.Ret()) elif isinstance(t1, uni.InferenceBool) or isinstance( t1, uni.InferenceTuple): raise NoFunctionInstanceError(self.name, arg_types)
def generate_code(self, arg_types: List[uni.InferenceType], code_builder: OpCodeBuilder): empty_label = code_builder.fresh_label() assert len( arg_types ) == 1, f'len function needs 1 argument, {len(arg_types)} where given' t = arg_types[0] assert isinstance(t, uni.InferenceList), f'Error during code generation of {self.name}: ' \ f'expects argument of type list, but type {t} was given' arg = gen_utils.Local(-1) code_builder.add(codes.LdLoc(arg)) code_builder.add(codes.BrFalse(empty_label)) if isinstance(t.t, uni.InferenceTypeVar): code_builder.add_print_str('Error: type var list has contents') code_builder.add(codes.Halt()) code_builder.add(codes.LdLoc(arg)) code_builder.add(codes.LdFld(FieldType.Tl)) code_builder.add_call(self.name, [t]) code_builder.add(codes.PushConst(1)) code_builder.add(codes.Add()) code_builder.add(codes.Ret()) code_builder.mark(empty_label) code_builder.add(codes.PushConst(0)) code_builder.add(codes.Ret())
def generate_code(self, arg_types: List[uni.InferenceType], code_builder: OpCodeBuilder): arg = gen_utils.Local(-1) assert len(arg_types) == 1, \ f'Error during code generation of \'{self.name}\': ' \ f'expected {self.num_args} argument but found {len(arg_types)}' arg_type = arg_types[0] assert not isinstance(arg_type, uni.InferenceTypeVar) and not isinstance(arg_type, uni.InferenceVoid), \ f'Error during code generation: could not generate {self.name} code for type {arg_type}' if isinstance(arg_type, uni.InferenceInt): code_builder.add(codes.LdLoc(arg)) code_builder.add(codes.PrintInt()) if isinstance(arg_type, uni.InferenceBool): false_label = code_builder.fresh_label() end_label = code_builder.fresh_label() code_builder.add(codes.LdLoc(arg)) code_builder.add(codes.BrFalse(false_label)) code_builder.add_print_str('True') code_builder.add(codes.Br(end_label)) code_builder.mark(false_label) code_builder.add_print_str('False') code_builder.mark(end_label) if isinstance(arg_type, uni.InferenceChar): code_builder.add(codes.LdLoc(arg)) code_builder.add(codes.PrintChar()) if isinstance(arg_type, uni.InferenceList): null_label = code_builder.fresh_label() end_label = code_builder.fresh_label() code_builder.add(codes.LdLoc(arg)) code_builder.add(codes.BrFalse(null_label)) if isinstance(arg_type.t, uni.InferenceTypeVar): code_builder.add_print_str('Error: type var list has contents') code_builder.add(codes.Halt()) else: code_builder.add(codes.LdLoc(arg)) code_builder.add(codes.LdFld(FieldType.Hd)) code_builder.add_call(self.name, [arg_type.t]) code_builder.add(codes.Pop()) # If not a str (list of char), then print cons operator in between if not isinstance(arg_type.t, uni.InferenceChar): code_builder.add_print_str(' : ') code_builder.add(codes.LdLoc(arg)) code_builder.add(codes.LdFld(FieldType.Tl)) code_builder.add_call(self.name, [uni.InferenceList(arg_type.t)]) code_builder.add(codes.Pop()) code_builder.add(codes.Br(end_label)) code_builder.mark(null_label) # End with empty list [] if not str if not isinstance(arg_type.t, uni.InferenceChar): code_builder.add_print_str('[]') code_builder.mark(end_label) if isinstance(arg_type, uni.InferenceTuple): code_builder.add_print_str('(') code_builder.add(codes.LdLoc(arg)) code_builder.add(codes.LdFld(FieldType.Fst)) code_builder.add_call(self.name, [arg_type.t1]) code_builder.add(codes.Pop()) code_builder.add_print_str(', ') code_builder.add(codes.LdLoc(arg)) code_builder.add(codes.LdFld(FieldType.Snd)) code_builder.add_call(self.name, [arg_type.t2]) code_builder.add(codes.Pop()) code_builder.add_print_str(')')
def generate_code(self, arg_types: List[uni.InferenceType], code_builder: OpCodeBuilder): assert len(arg_types) == 2, \ f'Error during code generation of \'{self.name}\': ' \ f'expected {self.num_args} arguments but found {len(arg_types)}' t1 = arg_types[0] t2 = arg_types[1] assert t1.is_equal(t2) or \ (isinstance(t1, uni.InferenceList) and isinstance(t1.t, uni.InferenceTypeVar) and isinstance(t2, uni.InferenceList) and isinstance(t2.t, uni.InferenceTypeVar)), \ f'Error during code generation: {self.name} expects both arguments to be of the same type' assert not isinstance(t1, uni.InferenceVoid), \ f'Error during code generation: could not generate {self.name} code for type {t1}' arg1 = gen_utils.Local(-1) arg2 = gen_utils.Local(-2) if isinstance(t1, uni.InferenceInt) or isinstance(t1, uni.InferenceBool) or isinstance(t1, uni.InferenceChar): code_builder.add(codes.LdLoc(arg1)) code_builder.add(codes.LdLoc(arg2)) code_builder.add(codes.Eq()) code_builder.add(codes.Ret()) elif isinstance(t1, uni.InferenceList): null_label = code_builder.fresh_label() false_label = code_builder.fresh_label() code_builder.add(codes.LdLoc(arg1)) code_builder.add(codes.BrFalse(null_label)) if isinstance(t1.t, uni.InferenceTypeVar): code_builder.add_print_str('Error: type var list has contents') code_builder.add(codes.Halt()) else: code_builder.add(codes.LdLoc(arg1)) code_builder.add(codes.LdFld(FieldType.Hd)) code_builder.add(codes.LdLoc(arg2)) code_builder.add(codes.LdFld(FieldType.Hd)) code_builder.add_call(self.name, [t1.t, t1.t]) code_builder.add(codes.BrFalse(false_label)) code_builder.add(codes.LdLoc(arg1)) code_builder.add(codes.LdFld(FieldType.Tl)) code_builder.add(codes.LdLoc(arg2)) code_builder.add(codes.LdFld(FieldType.Tl)) tail = uni.InferenceList(t1.t) code_builder.add_call(self.name, [tail, tail]) code_builder.add(codes.Ret()) code_builder.mark(null_label) code_builder.add(codes.LdLoc(arg1)) code_builder.add(codes.LdLoc(arg2)) code_builder.add(codes.Eq()) code_builder.add(codes.Ret()) code_builder.mark(false_label) code_builder.add(codes.PushConst(0)) code_builder.add(codes.Ret()) elif isinstance(t1, uni.InferenceTuple): false_label = code_builder.fresh_label() code_builder.add(codes.LdLoc(arg1)) code_builder.add(codes.LdFld(FieldType.Fst)) code_builder.add(codes.LdLoc(arg2)) code_builder.add(codes.LdFld(FieldType.Fst)) code_builder.add_call(self.name, [t1.t1, t1.t1]) code_builder.add(codes.BrFalse(false_label)) code_builder.add(codes.LdLoc(arg1)) code_builder.add(codes.LdFld(FieldType.Snd)) code_builder.add(codes.LdLoc(arg2)) code_builder.add(codes.LdFld(FieldType.Snd)) code_builder.add_call(self.name, [t1.t2, t1.t2]) code_builder.add(codes.Ret()) code_builder.mark(false_label) code_builder.add(codes.PushConst(0)) code_builder.add(codes.Ret())
def generate_code(self, code_builder: OpCodeBuilder): self.field.generate_code(code_builder) code_builder.add(codes.LdFld(self.field_type))