8000 WIP: Get the `Tree{T}` `prune` and `delete` methods working correctly, and also fix fundamentals of the `Tree{T}` type by dfellis · Pull Request #1100 · alantech/alan · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content
8000

WIP: Get the Tree{T} prune and delete methods working correctly, and also fix fundamentals of the Tree{T} type #1100

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions alan/test.ln
Original file line number Diff line number Diff line change
Expand Up @@ -1276,6 +1276,26 @@ export fn{Test} main {
// TODO: Get these tests working
// test.assert(eq, bayNode.parent!! ?? 'wrong', 'bar');
// test.assert(eq, myTree.children.map(fn (c: Node{string}) = c ?? 'wrong').join(', '), 'bar, baz');
})
.it('prune', fn (test: Mut{Testing}) {
let myTree = Tree('foo');
const barNode = myTree.addChild('bar');
const bazNode = barNode.addChild('baz');
const bayNode = barNode.addChild('bay');

barNode.prune;

test.assert(eq, myTree.rootNode.children.map(fn (c: Node{string}) = c ?? 'wrong').join(', '), '');
})
.it('delete', fn (test: Mut{Testing}) {
let myTree = Tree('foo');
const barNode = myTree.addChild('bar');
const bazNode = barNode.addChild('baz');
const bayNode = barNode.addChild('bay');

barNode.delete;

test.assert(eq, myTree.children.map(fn (c: Node{string}) = c!!).join(', '), 'baz, bay');
});

test.describe('Pack and Unpack')
Expand Down
44 changes: 44 additions & 0 deletions alan_compiler/src/lntojs/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -959,6 +959,7 @@ pub fn from_microstatement(
CType::Array(_) => Ok(enum_type.clone().to_callable_string()),
CType::Binds(..) => Ok(enum_type.clone().to_callable_string()),
CType::Tuple(_) => Ok(enum_type.clone().to_callable_string()),
CType::Either(_) => Ok(enum_type.clone().to_callable_string()),
otherwise => Err(format!("Cannot generate an constructor function for {} type as the input type has no name?, {:?}", function.name, otherwise)),
}?;
for t in ts {
Expand Down Expand Up @@ -1010,6 +1011,49 @@ pub fn from_microstatement(
}
return Ok((argstrs[0].clone(), out, deps));
}
CType::Either(ts)
if inner_type.clone().to_callable_string()
== enum_name =>
{
// Special-casing for Option and Result mapping. TODO:
// Make this more centralized
if ts.len() == 2 {
if let CType::Void = &*ts[1] {
if let CType::Void = &**t {
return Ok(("null".to_string(), out, deps));
} else {
return Ok((argstrs[0].clone(), out, deps));
}
} else if let CType::Type(name, _) = &*ts[1] {
if name == "Error" {
let (_, d) = typen::ctype_to_jtype(
ts[0].clone(),
deps,
)?;
deps = d;
let (_, d) = typen::ctype_to_jtype(
ts[1].clone(),
deps,
)?;
deps = d;
if let CType::Binds(..) = &**t {
return Ok((
argstrs[0].clone(),
out,
deps,
));
} else {
return Ok((
argstrs[0].clone(),
out,
deps,
));
}
}
}
}
return Ok((argstrs[0].clone(), out, deps));
}
CType::Field(n, _) if *n == enum_name => {
// Special-casing for Option and Result mapping. TODO:
// Make this more centralized
Expand Down
1 change: 1 addition & 0 deletions alan_compiler/src/lntors/typen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,7 @@ pub fn ctype_to_rtype(
_ => CType::fail("Bound types must be strings or rust imports"),
}
}
CType::BindsAs(a, _b) => ctype_to_rtype(a.clone(), deps),
CType::IntrinsicGeneric(name, _) => Ok((name.clone(), deps)), // How would this even be reached?
CType::Int(i) => Ok((i.to_string(), deps)),
CType::Float(f) => Ok((f.to_string(), deps)),
Expand Down
49 changes: 37 additions & 12 deletions alan_compiler/src/program/ctype.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pub enum CType {
Type(String, Arc<CType>),
Generic(String, Vec<String>, Arc<CType>),
Binds(Arc<CType>, Vec<Arc<CType>>),
BindsAs(Arc<CType>, Arc<CType>),
IntrinsicGeneric(String, usize),
IntCast(Arc<CType>),
Int(i128),
Expand Down Expand Up @@ -218,6 +219,13 @@ impl CType {
}
ctype_stack.push(n);
}
CType::BindsAs(a, b) => {
str_parts.push("BindsAs{");
ctype_stack.push(close_brace);
ctype_stack.push(b);
ctype_stack.push(comma);
ctype_stack.push(a);
}
CType::IntrinsicGeneric(s, l) => {
str_parts.push(s);
str_parts.push("{");
Expand Down Expand Up @@ -712,6 +720,13 @@ impl CType {
}
ctype_stack.push(n);
}
CType::BindsAs(a, b) => {
str_parts.push("BindsAs{");
ctype_stack.push(close_brace);
ctype_stack.push(b);
ctype_stack.push(comma);
ctype_stack.push(a);
}
CType::IntrinsicGeneric(s, u) => {
str_parts.push(s);
str_parts.push("{");
Expand Down Expand Up @@ -1287,7 +1302,8 @@ impl CType {
CType::Binds(t, ts) | CType::TIf(t, ts) => {
t.clone().has_infer() || ts.iter().any(|t| t.clone().has_infer())
}
CType::Function(a, b)
CType::BindsAs(a, b)
| CType::Function(a, b)
| CType::Call(a, b)
| CType::Dependency(a, b)
| CType::Import(a, b)
Expand Down Expand Up @@ -1333,6 +1349,7 @@ impl CType {
.map(|t| t.clone().degroup())
.collect::<Vec<Arc<CType>>>(),
)),
CType::BindsAs(a, b) => Arc::new(CType::BindsAs(a.clone().degroup(), b.clone().degroup())),
CType::IntrinsicGeneric(..) => self,
CType::IntCast(t) => Arc::new(CType::IntCast(t.clone().degroup())),
CType::Int(_) => self,
Expand Down Expand Up @@ -2714,6 +2731,7 @@ impl CType {
}
pub fn accepts(self: Arc<CType>, arg: Arc<CType>) -> bool {
match (&*self, &*arg) {
(_a, CType::BindsAs(_b, c)) => self.accepts(c.clone()),
(_a, CType::AnyOf(ts)) => {
for t in ts {
if self.clone().accepts(t.clone()) {
Expand Down Expand Up @@ -3159,17 +3177,19 @@ impl CType {
}
}
CType::Type(n, _) => {
// This is just an alias
fs.push(Arc::new(Function {
name: constructor_fn_name.clone(),
typen: Arc::new(CType::Function(
Arc::new(CType::Field(n.clone(), self.clone())),
t.clone(),
)),
microstatements: Vec::new(),
kind: FnKind::Derived,
origin_scope_path: scope.path.clone(),
}));
// This is just an alias, but avoid circular derives
if name != constructor_fn_name {
fs.push(Arc::new(Function {
name: constructor_fn_name.clone(),
typen: Arc::new(CType::Function(
Arc::new(CType::Field(n.clone(), self.clone())),
t.clone(),
)),
microstatements: Vec::new(),
kind: FnKind::Derived,
origin_scope_path: scope.path.clone(),
}));
}
}
CType::Tuple(ts) => {
// The constructor function needs to grab the types from all
Expand Down Expand Up @@ -3871,6 +3891,10 @@ impl CType {
.map(|gtr| gtr.clone().swap_subtype(old_type.clone(), new_type.clone()))
.collect::<Vec<Arc<CType>>>(),
)),
CType::BindsAs(a, b) => Arc::new(CType::BindsAs(
a.clone().swap_subtype(old_type.clone(), new_type.clone()),
b.clone().swap_subtype(old_type, new_type),
)),
CType::IntCast(i) => CType::intcast(i.clone().swap_subtype(old_type, new_type)),
CType::FloatCast(f) => CType::floatcast(f.clone().swap_subtype(old_type, new_type)),
CType::BoolCast(b) => CType::boolcast(b.clone().swap_subtype(old_type, new_type)),
Expand Down Expand Up @@ -5522,6 +5546,7 @@ pub fn typebaselist_to_ctype(
// TODO: Is there a better way to do this?
match name.as_str() {
"Binds" => CType::binds(args),
"BindsAs" => Arc::new(CType::BindsAs(args[0].clone(), args[1].clone())),
"Int" => CType::intcast(args[0].clone()),
"Float" => CType::floatcast(args[0].clone()),
"Bool" => CType::boolcast(args[0].clone()),
Expand Down
4 changes: 2 additions & 2 deletions alan_compiler/src/program/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -704,7 +704,7 @@ impl Function {
}
let res = match scope.functions.get(&f.name) {
None => Err("This should be impossible. Cannot get the function we just added to the scope"),
Some(fs) => Ok(fs.last().unwrap().clone()), // We know it's the last one
Some(fs) => Ok(fs.first().unwrap().clone()), // We know it's the first one
// because we just put it there
}?;
Ok((scope, res))
Expand Down Expand Up @@ -812,7 +812,7 @@ impl Function {
}
let res = match scope.functions.get(&f.name) {
None => Err("This should be impossible. Cannot get the function we just added to the scope"),
Some(fs) => Ok(fs.last().unwrap().clone()), // We know it's the last one
Some(fs) => Ok(fs.first().unwrap().clone()), // We know it's the first one
// because we just put it there
}?;
Ok((scope, res))
Expand Down
10 changes: 7 additions & 3 deletions alan_compiler/src/program/microstatement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -926,14 +926,15 @@ pub fn baseassignablelist_to_microstatements<'a>(
Some((mut temp_scope, fun)) => {
// Success! Let's emit this
// TODO: Do a better job at type rewriting here
let funargs = fun.args();
#[allow(clippy::needless_range_loop)]
for i in 0..fun.args().len() {
for i in 0..funargs.len() {
match &arg_microstatements[i] {
Microstatement::Value {
typen,
representation,
} => {
let actual_typen = fun.args()[i].2.clone();
let actual_typen = funargs[i].2.clone();
if typen != &actual_typen {
if matches!(&*actual_typen, CType::Function(..)) {
let temp_scope_2 = temp_scope.child();
Expand Down Expand Up @@ -1570,7 +1571,10 @@ pub fn statement_to_microstatements<'a>(
// TODO: Do we really need this temp_scope?
let temp_scope = scope.child();
match temp_scope.resolve_function(&"store".to_string(), &arg_types) {
Some((_, f)) => Ok(f),
Some((s, f)) => {
merge!(scope, s);
Ok(f)
}
None => Err(format!(
"Could not find store function with arguments {}",
arg_types
Expand Down
16 changes: 14 additions & 2 deletions alan_compiler/src/program/scope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ impl<'a> Scope<'a> {
| "Prefix" | "Method" | "Property" | "Cast" | "Own" | "Deref" | "Mut"
| "Rust" | "Nodejs" | "From" | "Array" | "Fail" | "Neg" | "Len" | "Size"
| "FileStr" | "Env" | "EnvExists" | "Not") => s = CType::from_generic(s, g, 1),
g @ ("Function" | "Call" | "Dependency" | "Import" | "Field"
g @ ("BindsAs" | "Function" | "Call" | "Dependency" | "Import" | "Field"
| "Prop" | "Buffer" | "Add" | "Sub" | "Mul" | "Div" | "Mod"
| "Pow" | "Min" | "Max" | "Concat" | "And" | "Or" | "Xor" | "Nand"
| "Nor" | "Xnor" | "Eq" | "Neq" | "Lt" | "Lte" | "Gt" | "Gte") => s = CType::from_generic(s, g, 2),
Expand Down Expand Up @@ -490,7 +490,19 @@ impl<'a> Scope<'a> {
let temp_scope = self.child();
match Function::from_generic_function(temp_scope, generic_f, generic_types.to_vec()) {
Err(_) => return None, // TODO: Should this be a panic?
Ok((_, realized_f)) => {
Ok((mut temp_scope, realized_f)) => {
// Don't merge the generic types
match &generic_f.kind {
FnKind::Generic(gen_args, _)
| FnKind::BoundGeneric(gen_args, _)
| FnKind::ExternalGeneric(gen_args, _, _) => {
for arg in gen_args {
temp_scope.types.remove(&arg.0);
}
}
_ => unreachable!(),
}
merge!(self, temp_scope);
return Some((self, realized_f));
}
}
Expand Down
Loading
Loading
0