Skip to content

Commit

Permalink
Add some function pointer conveniences + missing APIs
Browse files Browse the repository at this point in the history
  • Loading branch information
mustafaquraish committed Nov 4, 2023
1 parent e5d8e3a commit 158037a
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 12 deletions.
17 changes: 11 additions & 6 deletions bootstrap/stage0.c
Original file line number Diff line number Diff line change
Expand Up @@ -9945,11 +9945,13 @@ char *passes_code_generator_CodeGenerator_helper_gen_type(passes_code_generator_
} break;
case types_BaseType_Pointer: {
bool needs_parens = (((bool)cur->u.ptr) && (cur->u.ptr->base==types_BaseType_Function || cur->u.ptr->base==types_BaseType_Array));
if (needs_parens) {
if (cur->u.ptr->base==types_BaseType_Function) {
} else if (needs_parens) {
str_replace(&acc, format_string("(*%s)", acc));
} else {
str_replace(&acc, format_string("*%s", acc));
}

acc=passes_code_generator_CodeGenerator_helper_gen_type(this, top, cur->u.ptr, acc, false);
} break;
case types_BaseType_Array: {
Expand All @@ -9969,7 +9971,7 @@ char *passes_code_generator_CodeGenerator_helper_gen_type(passes_code_generator_
}

char *passes_code_generator_CodeGenerator_get_type_name_string(passes_code_generator_CodeGenerator *this, types_Type *type, char *name, bool is_func_def) {
ae_assert((type != NULL), "compiler/passes/code_generator.oc:890:12: Assertion failed: `type != null`", NULL); char *final = passes_code_generator_CodeGenerator_helper_gen_type(this, type, type, strdup(name), is_func_def);
ae_assert((type != NULL), "compiler/passes/code_generator.oc:892:12: Assertion failed: `type != null`", NULL); char *final = passes_code_generator_CodeGenerator_helper_gen_type(this, type, type, strdup(name), is_func_def);
str_strip_trailing_whitespace(final);
return final;
}
Expand Down Expand Up @@ -10019,7 +10021,7 @@ void passes_code_generator_CodeGenerator_gen_functions(passes_code_generator_Cod
ast_scopes_TemplateInstance *instance = std_vector_Iterator__8_cur(&__iter);
{
ast_scopes_Symbol *sym = instance->resolved;
ae_assert(sym->type==ast_scopes_SymbolType_Function, "compiler/passes/code_generator.oc:934:24: Assertion failed: `sym.type == Function`", NULL); ast_nodes_Function *func = sym->u.func;
ae_assert(sym->type==ast_scopes_SymbolType_Function, "compiler/passes/code_generator.oc:936:24: Assertion failed: `sym.type == Function`", NULL); ast_nodes_Function *func = sym->u.func;
passes_code_generator_CodeGenerator_gen_function(this, func);
}
}
Expand Down Expand Up @@ -10055,7 +10057,7 @@ void passes_code_generator_CodeGenerator_gen_function_decls(passes_code_generato
ast_scopes_TemplateInstance *instance = std_vector_Iterator__8_cur(&__iter);
{
ast_scopes_Symbol *sym = instance->resolved;
ae_assert(sym->type==ast_scopes_SymbolType_Function, "compiler/passes/code_generator.oc:961:24: Assertion failed: `sym.type == Function`", NULL); ast_nodes_Function *func = sym->u.func;
ae_assert(sym->type==ast_scopes_SymbolType_Function, "compiler/passes/code_generator.oc:963:24: Assertion failed: `sym.type == Function`", NULL); ast_nodes_Function *func = sym->u.func;
passes_code_generator_CodeGenerator_gen_function_decl(this, func);
if (func->exits)
std_buffer_Buffer_puts(&this->out, " __attribute__((noreturn))");
Expand Down Expand Up @@ -10729,10 +10731,13 @@ types_Type *passes_typechecker_TypeChecker_check_call(passes_typechecker_TypeChe
if (!((bool)res))
return NULL;

if ((res->base != types_BaseType_Function)) {
if ((res->base==types_BaseType_Pointer && res->u.ptr->base==types_BaseType_Function)) {
res=res->u.ptr;
} else if ((res->base != types_BaseType_Function)) {
passes_typechecker_TypeChecker_error(this, errors_Error_new(callee->span, format_string("Cannot call a non-function type: %s", types_Type_str(res))));
return NULL;
}

types_FunctionType func = res->u.func;
if ((((bool)func.orig) && func.orig->exits))
node->returns=true;
Expand Down Expand Up @@ -12089,7 +12094,7 @@ void passes_typechecker_TypeChecker_check_pre_import(passes_typechecker_TypeChec
std_map_Node__2 *it = std_map_Iterator__2_cur(&__iter);
{
ast_scopes_Symbol *sym = ast_scopes_Scope_lookup_recursive(passes_generic_pass_GenericPass_scope(this->o), it->key);
ae_assert(((bool)sym), "compiler/passes/typechecker.oc:1879:16: Assertion failed: `sym?`", "Should have added the symbol into scope already"); ae_assert(sym->type==ast_scopes_SymbolType_TypeDef, "compiler/passes/typechecker.oc:1880:16: Assertion failed: `sym.type == TypeDef`", NULL); types_Type *res = passes_typechecker_TypeChecker_resolve_type(this, it->value, false, true, true);
ae_assert(((bool)sym), "compiler/passes/typechecker.oc:1881:16: Assertion failed: `sym?`", "Should have added the symbol into scope already"); ae_assert(sym->type==ast_scopes_SymbolType_TypeDef, "compiler/passes/typechecker.oc:1882:16: Assertion failed: `sym.type == TypeDef`", NULL); types_Type *res = passes_typechecker_TypeChecker_resolve_type(this, it->value, false, true, true);
sym->u.type_def=res;
it->value=res;
}
Expand Down
8 changes: 4 additions & 4 deletions compiler/passes/code_generator.oc
Original file line number Diff line number Diff line change
Expand Up @@ -857,10 +857,10 @@ def CodeGenerator::helper_gen_type(&this, top: &Type, cur: &Type, acc: str, is_f
}

Pointer => {
let needs_parens = (cur.u.ptr? and
(cur.u.ptr.base == BaseType::Function or
cur.u.ptr.base == BaseType::Array))
if needs_parens {
let needs_parens = (cur.u.ptr? and cur.u.ptr.base == BaseType::Array)
if cur.u.ptr.base == BaseType::Function {
// No need to add extra * for function pointers
} else if needs_parens {
acc.replace(`(*{acc})`)
} else {
acc.replace(`*{acc}`)
Expand Down
6 changes: 4 additions & 2 deletions compiler/passes/typechecker.oc
Original file line number Diff line number Diff line change
Expand Up @@ -535,7 +535,10 @@ def TypeChecker::check_call(&this, node: &AST): &Type {
}
if not res? return null

if res.base != BaseType::Function {
if res.base == BaseType::Pointer and res.u.ptr.base == BaseType::Function {
res = res.u.ptr

} else if res.base != BaseType::Function {
.error(Error::new(callee.span, `Cannot call a non-function type: {res.str()}`))
return null
}
Expand All @@ -556,7 +559,6 @@ def TypeChecker::check_call(&this, node: &AST): &Type {
}

return func.return_type

}

def TypeChecker::check_pointer_arith(&this, node: &AST, _lhs: &Type, _rhs: &Type): &Type {
Expand Down
11 changes: 11 additions & 0 deletions std/deque.oc
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,15 @@ def Deque::back(&this): T {
return .data[.tail - 1]
}

def Deque::at(&this, index: u32): T {
assert index < .size, "Index out of bounds in Deque::at()"

return .data[(.head + index) % .capacity]
}

def Deque::free(&this) {
free(.data)
free(this)
}

def Deque::is_empty(&this): bool => .size == 0
48 changes: 48 additions & 0 deletions std/image/mod.oc
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,54 @@ def Image::load(filename: str): &Image {
return image
}

def interp(t: f32, a: f32, b: f32): f32 {
return a * (1.0 - t) + b * t
}

def bilinear_interp(t0: f32, t1: f32, a: f32, b: f32, c: f32, d: f32):f32 {
return interp(t1, interp(t0, a, b), interp(t0, c, d))
}

def Image::get_interpolated(&this, xf: f32, yf: f32): Color {
assert 0.0 <= xf < (.width as f32), `X coordinate out of bounds: {xf}`
assert 0.0 <= yf < (.height as f32), `Y coordinate out of bounds: {yf}`

let x_fl = xf as u32
let y_fl = yf as u32

let x_cl = if xf != (x_fl as f32) then x_fl + 1 else x_fl
let y_cl = if yf != (y_fl as f32) then y_fl + 1 else y_fl

let a = .get(x_fl, y_fl)
let b = .get(x_cl, y_fl)
let c = .get(x_fl, y_cl)
let d = .get(x_cl, y_cl)

let x_ratio = xf - (x_fl as f32)
let y_ratio = yf - (y_fl as f32)

let col = Color(
bilinear_interp(x_ratio, y_ratio, a.r as f32, b.r as f32, c.r as f32, d.r as f32) as u8,
bilinear_interp(x_ratio, y_ratio, a.g as f32, b.g as f32, c.g as f32, d.g as f32) as u8,
bilinear_interp(x_ratio, y_ratio, a.b as f32, b.b as f32, c.b as f32, d.b as f32) as u8,
)
return col
}

def Image::resize(&this, new_width: u32, new_height: u32): &Image {
let resized = Image::new(new_width, new_height)
let x_ratio = .width as f32 / new_width as f32
let y_ratio = .height as f32 / new_height as f32
for let ny = 0; ny < new_height; ++ny {
for let nx = 0; nx < new_width; ++nx {
let x = (nx as f32 * x_ratio)
let y = (ny as f32 * y_ratio)
resized.set(nx, ny, .get_interpolated(x, y))
}
}
return resized
}


def Image::clear(&this) {
std::libc::memset(.data, 0, .width * .height * sizeof(Color))
Expand Down
1 change: 1 addition & 0 deletions std/sdl.oc
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ def quit() extern("SDL_Quit")
def get_error(): str extern("SDL_GetError")
def create_window_renderer(width: i32, height: i32, flags: i32, window: &&Window, renderer: &&Renderer) extern("SDL_CreateWindowAndRenderer")
def delay(ms: i32) extern("SDL_Delay")
def get_ticks(): i32 extern("SDL_GetTicks")
def get_mouse_state(x: &i32, y: &i32): i32 extern("SDL_GetMouseState")
def get_relative_mouse_state(x: &i32, y: &i32): i32 extern("SDL_GetRelativeMouseState")
def show_cursor(toggle: bool) extern("SDL_ShowCursor")
Expand Down

0 comments on commit 158037a

Please sign in to comment.