def _codegen_Builtins_c_obj_alloc(self, node): ''' Allocates bytes for an object of the type submitted. Eventually we will be able to submit a type directly. For now, use a throwaway closure that generates an object of the type you want to use E.g., for an i32[8]: var x=c_obj_alloc({with var z:i32[8] z}) (the contents of the closure are optimized out at compile time) ''' expr = self._get_obj_noload(node) e2 = self.builder.load(expr) sizeof = self._obj_size(e2) call = self._codegen_Call( Call(node.position, 'c_alloc', [Number(node.position, sizeof, self.vartypes.u_size)])) b1 = self.builder.bitcast(call, expr.type) # pylint: disable=E1111 b2 = self.builder.alloca(b1.type) self.builder.store(b1, b2) b2.do_not_allocate = True b2.heap_alloc = True b2.tracked = True return b2
def _parse_standalone_vartype_expr(self): ''' Currently used for parsing variable types that are passed as an argument to a function. This is an exceptional case that will in time be eliminated. ''' pos = self.cur_tok.position vartype = self._parse_vartype_expr() # if we're invoking a type as a call, # then we call the __new__ method # for that type if self._cur_tok_is_punctuator('('): args = self._parse_argument_list(True) self._get_next_token() if vartype.is_obj_ptr(): v = vartype.pointee v = '.object.' + v.v_id else: v = vartype v = '.' + v.v_id return Call(pos, v + '.__new__', args, vartype) return VariableType(pos, vartype)
def _parse_builtin(self, name): if name in ('cast', 'convert'): return getattr(self, f'_parse_{name}_expr')() start = self.cur_tok.position self._get_next_token() self._match(TokenKind.PUNCTUATOR, '(', consume=False) args = self._parse_argument_list() self._get_next_token() return Call(start, name, args)
def _parse_convert_expr(self, callee='convert'): start = self.cur_tok.position self._get_next_token() self._match(TokenKind.PUNCTUATOR, '(') convert_from = self._parse_expression() self._match(TokenKind.PUNCTUATOR, ',') # For builtins that take a vartype as an argument, # we need to use this for now convert_to = self._parse_standalone_vartype_expr() #convert_to = self._parse_expression() self._match(TokenKind.PUNCTUATOR, ')') return Call(start, callee, [convert_from, convert_to])
def _parse_identifier_expr(self): start = self.cur_tok.position id_name = self.cur_tok.value if id_name in Builtins or id_name in Dunders: return self._parse_builtin(id_name) if id_name in self.consts: self._get_next_token() return self.consts[id_name] current = Variable(start, id_name, self.cur_tok.vartype) toplevel = current while True: self._get_next_token() if self._cur_tok_is_punctuator('['): current.child = self._parse_array_accessor() current = current.child continue elif self._cur_tok_is_punctuator('('): args = self._parse_argument_list() current.child = Call(start, id_name, args, self.cur_tok.vartype) current = current.child continue elif self.cur_tok.value == '.': self._get_next_token() current.child = Variable(start, self.cur_tok.value) current = current.child continue else: break return toplevel
def _codegen_Builtins_c_obj_free(self, node): ''' Deallocates memory for an object created with c_obj_alloc. ''' expr = self._get_obj_noload(node) if not expr.tracked: raise CodegenError(f'{node.args[0].name} is not an allocated object',node.args[0].position) # Mark the variable in question as untracked expr.tracked = False addr = self.builder.load(expr) addr2 = self.builder.bitcast(addr, self.vartypes.u_mem.as_pointer()).get_reference() call = self._codegen_Call( Call(node.position, 'c_free', [Number(node.position, addr2, self.vartypes.u_mem.as_pointer())])) # TODO: zero after free, automatically return call
def _codegen_dunder_methods(self, node): call = self._codegen_Call(Call(node.position, node.name, node.args), obj_method=True) return call
def _codegen_Builtins_out(self, node): in_template = re.split(r'([{}])', node.args[0].val) var_names = [] escape = False open_br = False for n in in_template: if n==r'{' and not escape: open_br = True continue if n==r'}' and not escape: open_br = False continue if open_br: var_ref = self._varaddr(n,False) var_names.append([var_ref.type.p_fmt,n]) continue escape=False if n and n[-1]=='\\': escape=True n=n[0:-1] n = n.replace('%','%%') var_names.append([n,None]) format_string = [] variable_list = [] for n in var_names: format_string.append(n[0]) if n[1] is None: continue if n[0] == '%s': var_app = Call( node.position, 'c_data', [Variable(node.position, n[1])] ) else: var_app = Variable(node.position, n[1]) variable_list.append(var_app) str_to_extract = String(node.position, ''.join(format_string)) convert = Call( node.position, 'c_data', [str_to_extract] ) variable_list.insert(0,convert) return self._codegen( Call( node.position, 'printf', variable_list, self.vartypes.i32 ) )