示例#1
0
    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())
示例#2
0
 def generate_code(self, code_builder: OpCodeBuilder):
     while_label = code_builder.fresh_label()
     end_label = code_builder.fresh_label()
     code_builder.mark(while_label)
     self.expression.generate_code(code_builder)
     code_builder.add(codes.BrFalse(end_label))
     self.body.generate_code(code_builder)
     code_builder.add(codes.Br(while_label))
     code_builder.mark(end_label)
示例#3
0
    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)
示例#4
0
 def generate_code(self, code_builder: OpCodeBuilder):
     end_label = code_builder.fresh_label()
     else_label = code_builder.fresh_label(
     ) if self.else_block is not None else end_label
     self.expression.generate_code(code_builder)
     code_builder.add(codes.BrFalse(else_label))
     self.then_block.generate_code(code_builder)
     if self.else_block is not None:
         code_builder.add(codes.Br(end_label))
         code_builder.mark(else_label)
         self.else_block.generate_code(code_builder)
     code_builder.mark(end_label)
示例#5
0
    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())
示例#6
0
    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(')')