Skip to content

Commit

Permalink
Progress on ffi by allowing better namespace resolution. Still needs …
Browse files Browse the repository at this point in the history
…work
  • Loading branch information
jimmyhmiller committed Oct 26, 2024
1 parent 5243fe0 commit a8d785e
Show file tree
Hide file tree
Showing 8 changed files with 126 additions and 47 deletions.
2 changes: 1 addition & 1 deletion TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@
* I need the ability to re-export functions without a level of indirection
* Figure out a print system for types like the vector
* I need to do indexing with [] I just need to figure out how to distinguish a literal and indexing. How do other languages do that?
* Make namespacing reference work for structs and enums
* Make namespacing reference work for structs and enums better
21 changes: 21 additions & 0 deletions resources/beagle.ffi.bg
Original file line number Diff line number Diff line change
@@ -1,6 +1,27 @@
namespace beagle.ffi


// Probably should move this stuff to an ffi namespace
struct Library {
id
}

fn __make_lib_struct(id) {
Library { id: id }
}

enum Type {
U32,
I32,
Pointer,
MutablePointer,
String,
Void,
}

// TODO: I could make a function that maps between a type an integer
// but I don't actually have equality defined for structures

fn __create_ffi_function(ffi_info) {
fn() {
call_ffi_info(ffi_info)
Expand Down
2 changes: 1 addition & 1 deletion resources/ffi_test.bg
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import "beagle.ffi" as ffi
// That's a bit ugly though. But maybe it's a start
fn main() {
let sdl = ffi/load_library("/opt/homebrew/lib/libSDL2-2.0.0.dylib")
let sdl_init = ffi/get_function(sdl, "SDL_Init", [], null)
let sdl_init = ffi/get_function(sdl, "SDL_Init", [ffi/Type.U32], ffi/Type.I32)
sdl_init(0)

println(sdl)
Expand Down
9 changes: 9 additions & 0 deletions resources/namespace_resolution_test.bg
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace namespace_resolution_test

import "top_level" as top_level
import "enum_test" as enum_test

fn main() {
println(top_level/x)
println(enum_test/Action.run { speed: 2 })
}
20 changes: 0 additions & 20 deletions resources/std.bg
Original file line number Diff line number Diff line change
Expand Up @@ -47,26 +47,6 @@ fn atom(value) {
}


// Probably should move this stuff to an ffi namespace
struct Library {
id
}

fn __make_lib_struct(id) {
Library { id: id }
}

// If I'm going to make this work, I'm going to need arrays...

enum Type {
U32,
I32,
Pointer,
MutablePointer,
String,
Void,
}

// TODO: Need a way to re-export rather than wrap
fn get(coll, i) {
persistent_vector/get(coll, i)
Expand Down
79 changes: 57 additions & 22 deletions src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,7 @@ impl<'a> AstCompiler<'a> {
let namespace_id = self
.compiler
.find_binding(self.compiler.current_namespace_id(), &name)
.unwrap();
.unwrap_or_else(|| panic!("binding not found {}", name));
let value_reg = self.ir.assign_new(value);
self.store_namespaced_variable(Value::RawValue(namespace_id), value_reg);
// TODO: This should probably return the enum value
Expand All @@ -448,6 +448,7 @@ impl<'a> AstCompiler<'a> {
variant,
fields,
} => {
let (namespace, name) = self.get_namespace_name_and_name(&name);
let field_results = fields
.iter()
.map(|field| {
Expand All @@ -458,7 +459,7 @@ impl<'a> AstCompiler<'a> {

let (struct_id, struct_type) = self
.compiler
.get_struct(&format!("{}.{}", name, variant))
.get_struct(&format!("{}/{}.{}", namespace, name, variant))
.unwrap_or_else(|| panic!("Struct not found {}", name));

for field in fields.iter() {
Expand Down Expand Up @@ -499,6 +500,7 @@ impl<'a> AstCompiler<'a> {
.tag(struct_pointer, BuiltInTypes::HeapObject.get_tag())
}
Ast::StructCreation { name, fields } => {
let (namespace, name) = self.get_namespace_name_and_name(&name);
for field in fields.iter() {
self.not_tail_position();
let value = self.call_compile(&field.1);
Expand All @@ -508,8 +510,10 @@ impl<'a> AstCompiler<'a> {

let (struct_id, struct_type) = self
.compiler
.get_struct(&name)
.unwrap_or_else(|| panic!("Struct not found {}", name));
.get_struct(&format!("{}/{}", namespace, name))
.unwrap_or_else(|| {
panic!("Struct not found {}/{}", namespace, name)
});

let mut field_order: Vec<usize> = vec![];
for field in fields.iter() {
Expand Down Expand Up @@ -1212,9 +1216,18 @@ impl<'a> AstCompiler<'a> {
}

fn get_variable_alloc_free_variable(&mut self, name: &str) -> VariableLocation {
// TODO: Should walk the environment stack
if let Some(variable) = self.get_variable_in_stack(name) {
variable.clone()
} else if name.contains("/") {
let (namespace_name, name) = self.get_namespace_name_and_name(name);
let namespace_id = self.compiler.get_namespace_id(&namespace_name).unwrap();

let slot = self
.compiler
.find_binding(namespace_id, &name)
.unwrap_or_else(|| panic!("Can't find variable {}", name));

VariableLocation::NamespaceVariable(namespace_id, slot)
} else {
let current_env = self.environment_stack.last_mut().unwrap();
current_env.free_variables.push(name.to_string());
Expand Down Expand Up @@ -1295,8 +1308,9 @@ impl<'a> AstCompiler<'a> {
}
}
Ast::Struct { name, fields } => {
let (namespace, name) = self.get_namespace_name_and_name(name);
self.compiler.add_struct(Struct {
name: name.clone(),
name: format!("{}/{}", namespace, name),
fields: fields
.iter()
.map(|field| {
Expand All @@ -1310,8 +1324,9 @@ impl<'a> AstCompiler<'a> {
});
}
Ast::Enum { name, variants } => {
let (namespace, name) = self.get_namespace_name_and_name(name);
let enum_repr = Enum {
name: name.clone(),
name: format!("{}/{}", namespace, name),
variants: variants
.iter()
.map(|variant| match variant {
Expand Down Expand Up @@ -1339,8 +1354,9 @@ impl<'a> AstCompiler<'a> {
.collect(),
};

let (namespace, name) = self.get_namespace_name_and_name(&name);
self.compiler.add_struct(Struct {
name: name.to_string(),
name: format!("{}/{}", namespace, name),
fields: variants
.iter()
.map(|variant| match variant {
Expand All @@ -1357,22 +1373,26 @@ impl<'a> AstCompiler<'a> {
Ast::EnumVariant {
name: variant_name,
fields,
} => self.compiler.add_struct(Struct {
name: format!("{}.{}", name, variant_name),
fields: fields
.iter()
.map(|field| {
if let Ast::Identifier(name) = field {
name.clone()
} else {
panic!("Expected identifier got {:?}", field)
}
})
.collect(),
}),
} => {
let (namespace, name) = self.get_namespace_name_and_name(&name);
self.compiler.add_struct(Struct {
name: format!("{}/{}.{}", namespace, name, variant_name),
fields: fields
.iter()
.map(|field| {
if let Ast::Identifier(name) = field {
name.clone()
} else {
panic!("Expected identifier got {:?}", field)
}
})
.collect(),
})
}
Ast::EnumStaticVariant { name: variant_name } => {
let (namespace, name) = self.get_namespace_name_and_name(&name);
self.compiler.add_struct(Struct {
name: format!("{}.{}", name, variant_name),
name: format!("{}/{}.{}", namespace, name, variant_name),
fields: vec![],
});
}
Expand Down Expand Up @@ -1417,6 +1437,21 @@ impl<'a> AstCompiler<'a> {
let name = self.name.as_ref()?;
Some(self.compiler.current_namespace_name() + "/" + name)
}

fn get_namespace_name_and_name(&self, name: &str) -> (String, String) {
if name.contains("/") {
let parts: Vec<&str> = name.split("/").collect();
let alias = parts[0];
let name = parts[1];
let namespace = self
.compiler
.get_namespace_from_alias(alias)
.unwrap_or_else(|| panic!("Can't find alias {}", alias));
(namespace, name.to_string())
} else {
(self.compiler.current_namespace_name(), name.to_string())
}
}
}

impl From<i64> for Ast {
Expand Down
24 changes: 23 additions & 1 deletion src/builtins.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use core::panic;
use std::{
error::Error,
mem,
Expand Down Expand Up @@ -257,13 +258,34 @@ pub unsafe extern "C" fn load_library<Alloc: Allocator>(

let call_fn = runtime
.compiler
.get_function_by_name("beagle.core/__make_lib_struct")
.get_function_by_name("beagle.ffi/__make_lib_struct")
.unwrap();
let function_pointer = runtime.compiler.get_pointer(call_fn).unwrap();
let function: fn(usize) -> usize = std::mem::transmute(function_pointer);
function(id)
}

#[allow(unused)]
pub fn map_ffi_types<Alloc: Allocator>(runtime: &Runtime<Alloc>, value: usize) -> Type {
let heap_object = HeapObject::from_tagged(value);
let struct_id = heap_object.get_struct_id();
let struct_info = runtime.compiler.get_struct_by_id(struct_id).unwrap();
let name = struct_info.name.as_str().split_once("/").unwrap().1;
match name {
"U32" => Type::u32(),
"I32" => Type::i32(),
"Pointer" => Type::pointer(),
"MutablePointer" => Type::pointer(),
"String" => Type::pointer(),
"Void" => Type::void(),
_ => panic!("Unknown type"),
}
}

// TODO:
// I need to get the elements of this vector into
// a rust vector and then map the typess

pub unsafe extern "C" fn get_function<Alloc: Allocator>(
runtime: *mut Runtime<Alloc>,
library_id: usize,
Expand Down
16 changes: 14 additions & 2 deletions src/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -955,7 +955,10 @@ impl Compiler {
// struct Point { x y }
// and then you say let x = Point
// x is a struct object that describes the struct Point
self.namespaces.add_binding(&name, 0);

// grab the simple name for the binding
let (_, simple_name) = name.split_once("/").unwrap();
self.namespaces.add_binding(simple_name, 0);
}

pub fn add_enum(&mut self, e: Enum) {
Expand All @@ -981,7 +984,8 @@ impl Compiler {
) -> Option<String> {
// It should look like this
// struct_name { field1: value1, field2: value2 }
let mut repr = struct_value.name.clone();
let simple_name = struct_value.name.split_once("/").unwrap().1;
let mut repr = simple_name.to_string();
if struct_value.fields.is_empty() {
return Some(repr);
}
Expand Down Expand Up @@ -1103,6 +1107,10 @@ impl Compiler {
namespace.aliases.insert(alias, namespace_id);
}

pub fn get_namespace_id(&self, name: &str) -> Option<usize> {
self.namespaces.get_namespace_id(name)
}

/// TODO: Temporary please fix
fn get_file_name_from_import(&self, import_name: String) -> String {
let mut exe_path = env::current_exe().unwrap();
Expand Down Expand Up @@ -1146,6 +1154,10 @@ impl Compiler {
_ => panic!("Not an import"),
}
}

pub fn get_struct_by_id(&self, struct_id: usize) -> Option<&Struct> {
self.structs.get_by_id(struct_id)
}
}

impl fmt::Debug for Compiler {
Expand Down

0 comments on commit a8d785e

Please sign in to comment.