void mesh_render(mesh_s *mesh) { for(int i = 0 ; i < array_length(mesh->attributes); i++) { mesh_attribute_s *attribute = array_get_ptr(mesh->attributes) + i; GLint location = glGetAttribLocation(mesh->program, attribute->name); if(location >= 0) { glBindBuffer(GL_ARRAY_BUFFER, attribute->buffer); glVertexAttribPointer( location, attribute->components, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * attribute->components, (void *)0); glEnableVertexAttribArray(location); } } glUseProgram(mesh->program); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->elements.buffer); glDrawElements( GL_TRIANGLES, mesh->elements.count, GL_UNSIGNED_INT, (void *)0); glUseProgram(0); for(int i = 0 ; i < array_length(mesh->attributes); i++) { mesh_attribute_s *attribute = array_get_ptr(mesh->attributes) + i; GLint location = glGetAttribLocation(mesh->program, attribute->name); if(location >= 0) { glDisableVertexAttribArray(location); } } glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); }
static void handle_tick(game_context_s *context, void *data, const nothing_s *n) { input_handler_s *input_handler = data; // process the callback-based events target_context = context; glfwPollEvents(); target_context = NULL; // process joysticks for(int i = 0; i < MAX_JOYSTICKS; i++) { if(glfwGetJoystickParam(i, GLFW_PRESENT) == GL_TRUE) { joystick_event_s *joystick = &input_handler->joysticks[i]; int axis_count = glfwGetJoystickParam(i, GLFW_AXES); array_set_length(joystick->axes, axis_count); glfwGetJoystickPos(i, array_get_ptr(joystick->axes), axis_count); int button_count = glfwGetJoystickParam(i, GLFW_BUTTONS); array_set_length(joystick->buttons, button_count); glfwGetJoystickButtons(i, array_get_ptr(joystick->buttons), button_count); broadcast_input_handler_joystick_event(context, *joystick); } } }
/** Evaluate a function call */ value_t eval_call( clos_t* callee, array_t* arg_exprs, clos_t* caller, value_t* caller_locals ) { ast_fun_t* fptr = callee->fun; assert (fptr != NULL); if (arg_exprs->len != fptr->param_decls->len) { printf("argument count mismatch\n"); exit(-1); } // Allocate space for the local variables value_t* callee_locals = alloca( sizeof(value_t) * fptr->local_decls->len ); // Allocate mutable cells for the escaping variables for (size_t i = 0; i < fptr->esc_locals->len; ++i) { ast_decl_t* decl = array_get(fptr->esc_locals, i).word.decl; assert (decl->esc); assert (decl->idx < fptr->local_decls->len); callee_locals[decl->idx] = value_from_obj((heapptr_t)cell_alloc()); } // Evaluate the argument values for (size_t i = 0; i < arg_exprs->len; ++i) { //printf("evaluating arg %ld\n", i); heapptr_t param_decl = array_get_ptr(fptr->param_decls, i); // Evaluate the parameter value value_t arg_val = eval_expr( array_get_ptr(arg_exprs, i), caller, caller_locals ); // Assign the value to the parameter eval_assign( param_decl, arg_val, callee, callee_locals ); } // Evaluate the unit function body in the local frame return eval_expr(fptr->body_expr, callee, callee_locals); }
void mesh_set_attribute( mesh_s *mesh, const char *name, GLint components, GLsizei size, GLfloat *attribute_data) { mesh_attribute_s *target_attribute = NULL; for(int i = 0; i < array_length(mesh->attributes); i++) { if(strcmp(array_get(mesh->attributes, i).name, name) == 0) { target_attribute = array_get_ptr(mesh->attributes) + i; } } if(target_attribute == NULL) { mesh_attribute_s new_attribute = {NULL, 0}; array_add(mesh->attributes, new_attribute); target_attribute = array_get_ptr(mesh->attributes) + array_length(mesh->attributes) - 1; } if(target_attribute->name == NULL) { char *name_buf = malloc(strlen(name) + 1); strcpy(name_buf, name); target_attribute->name = name_buf; } if(target_attribute->buffer != 0) glDeleteBuffers(1, &target_attribute->buffer); target_attribute->buffer = graphics_make_buffer( GL_ARRAY_BUFFER, size, attribute_data, GL_STATIC_DRAW); target_attribute->components = components; }
void mesh_release(mesh_s *mesh) { if(mesh->elements.buffer != 0) glDeleteBuffers(1, &mesh->elements.buffer); for(int i = 0; i < array_length(mesh->attributes); i++) { mesh_attribute_s *attribute = array_get_ptr(mesh->attributes) + i; free((char *)attribute->name); glDeleteBuffers(1, &attribute->buffer); } array_release(mesh->attributes); free(mesh); }
/** Resolve variables in a given function */ void var_res_pass(ast_fun_t* fun, ast_fun_t* parent) { fun->parent = parent; // Add the function parameters to the local scope for (size_t i = 0; i < fun->param_decls->len; ++i) { find_decls( array_get_ptr(fun->param_decls, i), fun ); assert (array_get(fun->param_decls, i).word.decl->fun == fun); } // Find declarations in the function body find_decls(fun->body_expr, fun); // Resolve variable references var_res(fun->body_expr, fun); }
/** Evaluate a host function call */ value_t eval_host_call( hostfn_t* callee, array_t* arg_exprs, clos_t* caller, value_t* caller_locals ) { value_t* arg_vals = alloca(sizeof(value_t) * arg_exprs->len); if (arg_exprs->len != callee->num_params) { printf( "argument count mismatch in call to %s, got %d, expected %d\n", string_cstr(callee->name), arg_exprs->len, callee->num_params ); exit(-1); } // Evaluate the argument values for (size_t i = 0; i < arg_exprs->len; ++i) { //printf("evaluating arg %ld\n", i); // Evaluate the parameter value arg_vals[i] = eval_expr( array_get_ptr(arg_exprs, i), caller, caller_locals ); } // Type test signature if (callee->sig_str == vm_get_cstr("bool(tag)")) { bool (*fptr)(tag_t) = callee->fptr; return fptr(arg_vals[0].tag)? VAL_TRUE:VAL_FALSE; } if (callee->sig_str == vm_get_cstr("void(int)")) { void (*fptr)(int) = callee->fptr; fptr(arg_vals[0].word.int32); return VAL_TRUE; } if (callee->sig_str == vm_get_cstr("void(int64)")) { void (*fptr)(int64_t) = callee->fptr; fptr(arg_vals[0].word.int64); return VAL_TRUE; } if (callee->sig_str == vm_get_cstr("void(string)")) { void (*fptr)(string_t*) = callee->fptr; fptr(arg_vals[0].word.string); return VAL_TRUE; } if (callee->sig_str == vm_get_cstr("string()")) { string_t* (*fptr)() = callee->fptr; string_t* str = fptr(); return value_from_heapptr((heapptr_t)str, TAG_STRING); } if (callee->sig_str == vm_get_cstr("string(string)")) { string_t* (*fptr)(string_t*) = callee->fptr; string_t* str = fptr(arg_vals[0].word.string); return value_from_heapptr((heapptr_t)str, TAG_STRING); } printf("unsupported host function signature\n"); exit(-1); }
void var_res(heapptr_t expr, ast_fun_t* fun) { // Get the shape of the AST node shapeidx_t shape = get_shape(expr); // Constants and strings, do nothing if (shape == SHAPE_AST_CONST || shape == SHAPE_STRING) { return; } // Array literal expression if (shape == SHAPE_ARRAY) { array_t* array_expr = (array_t*)expr; for (size_t i = 0; i < array_expr->len; ++i) var_res(array_get(array_expr, i).word.heapptr, fun); return; } // Object literal expression if (shape == SHAPE_AST_OBJ) { ast_obj_t* obj_expr = (ast_obj_t*)expr; if (obj_expr->proto_expr) var_res(obj_expr->proto_expr, fun); for (size_t i = 0; i < obj_expr->val_exprs->len; ++i) var_res(array_get(obj_expr->val_exprs, i).word.heapptr, fun); return; } // Variable declaration, do nothing if (shape == SHAPE_AST_DECL) { return; } // Variable reference if (shape == SHAPE_AST_REF) { ast_ref_t* ref = (ast_ref_t*)expr; // Find the declaration for this reference ast_decl_t* decl = find_decl(ref, fun); if (decl == NULL) { printf("unresolved reference to \"%s\"\n", string_cstr(ref->name)); exit(-1); } // Store the declaration on the reference assert (decl->fun != NULL); ref->decl = decl; // If the variable is from this scope if (decl->fun == fun) { // Store the index of this local assert (decl->idx < fun->local_decls->len); ref->idx = decl->idx; } else { // Mark the variable as escaping decl->esc = true; // Thread the escaping variable through nested functions thread_esc_var(ref, fun, fun); // Find the mutable cell index for the variable ref->idx = array_indexof_ptr(fun->free_vars, (heapptr_t)ref->decl); assert (ref->idx < fun->free_vars->len); } return; } // Sequence/block expression if (shape == SHAPE_AST_SEQ) { ast_seq_t* seqexpr = (ast_seq_t*)expr; array_t* expr_list = seqexpr->expr_list; for (size_t i = 0; i < expr_list->len; ++i) var_res(array_get_ptr(expr_list, i), fun); return; } // Binary operator (e.g. a + b) if (shape == SHAPE_AST_BINOP) { ast_binop_t* binop = (ast_binop_t*)expr; var_res(binop->left_expr, fun); var_res(binop->right_expr, fun); return; } // Unary operator (e.g. -a) if (shape == SHAPE_AST_UNOP) { ast_unop_t* unop = (ast_unop_t*)expr; var_res(unop->expr, fun); return; } // If expression if (shape == SHAPE_AST_IF) { ast_if_t* ifexpr = (ast_if_t*)expr; var_res(ifexpr->test_expr, fun); var_res(ifexpr->then_expr, fun); var_res(ifexpr->else_expr, fun); return; } // Function/closure expression if (shape == SHAPE_AST_FUN) { ast_fun_t* child_fun = (ast_fun_t*)expr; // Resolve variable references in the nested child function var_res_pass(child_fun, fun); return; } // Function call if (shape == SHAPE_AST_CALL) { ast_call_t* callexpr = (ast_call_t*)expr; array_t* arg_exprs = callexpr->arg_exprs; var_res(callexpr->fun_expr, fun); for (size_t i = 0; i < arg_exprs->len; ++i) var_res(array_get_ptr(arg_exprs, i), fun); return; } // Unsupported AST node type assert (false); }
/** Find all declarations within an AST subtree */ void find_decls(heapptr_t expr, ast_fun_t* fun) { assert (expr != NULL); // Get the shape of the AST node shapeidx_t shape = get_shape(expr); // Constants and strings, do nothing if (shape == SHAPE_AST_CONST || shape == SHAPE_STRING) { return; } // Array literal expression if (shape == SHAPE_ARRAY) { array_t* array_expr = (array_t*)expr; for (size_t i = 0; i < array_expr->len; ++i) find_decls(array_get(array_expr, i).word.heapptr, fun); return; } // Object literal expression if (shape == SHAPE_AST_OBJ) { ast_obj_t* obj_expr = (ast_obj_t*)expr; if (obj_expr->proto_expr) find_decls(obj_expr->proto_expr, fun); for (size_t i = 0; i < obj_expr->val_exprs->len; ++i) find_decls(array_get(obj_expr->val_exprs, i).word.heapptr, fun); return; } // Variable or constant declaration (let/var) if (shape == SHAPE_AST_DECL) { ast_decl_t* decl = (ast_decl_t*)expr; // Mark the declaration as belonging to this function assert (fun != NULL); decl->fun = fun; // If this variable is already declared, do nothing for (size_t i = 0; i < fun->local_decls->len; ++i) { ast_decl_t* local = array_get(fun->local_decls, i).word.decl; if (local->name == decl->name) return; } decl->idx = fun->local_decls->len; array_set_obj(fun->local_decls, decl->idx, (heapptr_t)decl); return; } // Variable reference if (shape == SHAPE_AST_REF) { return; } // Sequence/block expression if (shape == SHAPE_AST_SEQ) { ast_seq_t* seqexpr = (ast_seq_t*)expr; array_t* expr_list = seqexpr->expr_list; for (size_t i = 0; i < expr_list->len; ++i) find_decls(array_get(expr_list, i).word.heapptr, fun); return; } // Binary operator (e.g. a + b) if (shape == SHAPE_AST_BINOP) { ast_binop_t* binop = (ast_binop_t*)expr; find_decls(binop->left_expr, fun); find_decls(binop->right_expr, fun); return; } // Unary operator (e.g. -1) if (shape == SHAPE_AST_UNOP) { ast_unop_t* unop = (ast_unop_t*)expr; find_decls(unop->expr, fun); return; } // If expression if (shape == SHAPE_AST_IF) { ast_if_t* ifexpr = (ast_if_t*)expr; find_decls(ifexpr->test_expr, fun); find_decls(ifexpr->then_expr, fun); find_decls(ifexpr->else_expr, fun); return; } // Function/closure expression if (shape == SHAPE_AST_FUN) { // Do nothing. Variables declared in the nested // function are not of this scope return; } // Function call if (shape == SHAPE_AST_CALL) { ast_call_t* callexpr = (ast_call_t*)expr; array_t* arg_exprs = callexpr->arg_exprs; find_decls(callexpr->fun_expr, fun); for (size_t i = 0; i < arg_exprs->len; ++i) find_decls(array_get_ptr(arg_exprs, i), fun); return; } // Unsupported AST node type assert (false); }