Skip to content

Commit

Permalink
Implement operator support, testing with i64 math, and fix formatting (
Browse files Browse the repository at this point in the history
  • Loading branch information
dfellis authored Mar 6, 2024
1 parent 17c51e0 commit 0d95d50
Show file tree
Hide file tree
Showing 7 changed files with 624 additions and 182 deletions.
96 changes: 24 additions & 72 deletions src/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,132 +263,84 @@ test!(int16_max => r#"
);

test!(int32_add => r#"
from @std/app import start, print, exit
on start {
add(1.toInt32(), 2.toInt32()).print();
emit exit 0;
export fn main {
add(1.i32(), 2.i32()).print();
}"#;
stdout "3\n";
);
test!(int32_sub => r#"
from @std/app import start, print, exit
on start {
sub(2.toInt32(), 1.toInt32()).print();
emit exit 0;
export fn main {
sub(2.i32(), 1.i32()).print();
}"#;
stdout "1\n";
);
test!(int32_mul => r#"
from @std/app import start, print, exit
on start {
mul(2.toInt32(), 1.toInt32()).print();
emit exit 0;
export fn main {
mul(2.i32(), 1.i32()).print();
}"#;
stdout "2\n";
);
test!(int32_div => r#"
from @std/app import start, print, exit
on start {
div(6.toInt32(), 2.toInt32()).print();
emit exit 0;
export fn main {
div(6.i32(), 2.i32()).print();
}"#;
stdout "3\n";
);
test!(int32_mod => r#"
from @std/app import start, print, exit
on start {
mod(6.toInt32(), 4.toInt32()).print();
emit exit 0;
export fn main {
mod(6.i32(), 4.i32()).print();
}"#;
stdout "2\n";
);
test!(int32_pow => r#"
from @std/app import start, print, exit
on start {
pow(6.toInt32(), 2.toInt32()).print();
emit exit 0;
export fn main {
pow(6.i32(), 2.i32()).print();
}"#;
stdout "36\n";
);
test!(int32_min => r#"
from @std/app import start, print, exit
on start {
min(3.toInt32(), 5.toInt32()).print();
emit exit 0;
export fn main {
min(3.i32(), 5.i32()).print();
}"#;
stdout "3\n";
);
test!(int32_max => r#"
from @std/app import start, print, exit
on start {
max(3.toInt32(), 5.toInt32()).print();
emit exit 0;
export fn main {
max(3.i32(), 5.i32()).print();
}"#;
stdout "5\n";
);

test!(int64_add => r#"
from @std/app import start, print, exit
on start {
print(1 + 2);
emit exit 0;
}"#;
export fn main = print(1 + 2);"#;
stdout "3\n";
);
test!(int64_sub => r#"
from @std/app import start, print, exit
on start {
print(2 - 1);
emit exit 0;
}"#;
export fn main = print(2 - 1);"#;
stdout "1\n";
);
test!(int64_mul => r#"
from @std/app import start, print, exit
on start {
print(2 * 1);
emit exit 0;
}"#;
export fn main = print(2 * 1);"#;
stdout "2\n";
);
test!(int64_div => r#"
from @std/app import start, print, exit
on start {
print(6 / 2);
emit exit 0;
}"#;
export fn main = print(6 / 2);"#;
stdout "3\n";
);
test!(int64_mod => r#"
from @std/app import start, print, exit
on start {
print(6 % 4);
emit exit 0;
}"#;
export fn main = print(6 % 4);"#;
stdout "2\n";
);
test!(int64_pow => r#"
from @std/app import start, print, exit
on start {
print(6 ** 2);
emit exit 0;
}"#;
export fn main = print(6 ** 2);"#;
stdout "36\n";
);
test!(int64_min => r#"
from @std/app import start, print, exit
on start {
min(3, 5).print();
emit exit 0;
}"#;
export fn main = min(3, 5).print();"#;
stdout "3\n";
);
test!(int64_max => r#"
from @std/app import start, print, exit
on start {
max(3.toInt64(), 5.toInt64()).print();
emit exit 0;
}"#;
export fn main = max(3.i64(), 5.i64()).print();"#;
stdout "5\n";
);

Expand Down
54 changes: 29 additions & 25 deletions src/lntors/event.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
// Builds the event functions using the code from their handlers. Currently an O(n^2) algo for
// simplicity.

use crate::program::{Function, Microstatement, Program};
use crate::lntors::function::from_microstatement;
use crate::program::{Function, Microstatement, Program};

pub fn generate(
program: &Program,
) -> Result<String, Box<dyn std::error::Error>> {
pub fn generate(program: &Program) -> Result<String, Box<dyn std::error::Error>> {
// The events will all go into an `event` sub-module with every function marked public. These
// event functions are what the `emit <eventName> <optionalValue>;` statements will call, so
// something like:
Expand All @@ -28,13 +26,14 @@ pub fn generate(
for (_, (_, _, eventscope)) in program.scopes_by_file.iter() {
for (eventname, event) in eventscope.events.iter() {
// Define the function for this event
out = format!("{} pub fn {}{} {{\n",
out,
eventname,
match event.typename.as_str() {
"void" => "".to_string(),
x => format!("(arg: {})", x).to_string(),
},
out = format!(
"{} pub fn {}{} {{\n",
out,
eventname,
match event.typename.as_str() {
"void" => "".to_string(),
x => format!("(arg: {})", x).to_string(),
},
);
let expected_arg_type = match event.typename.as_str() {
"void" => None,
Expand All @@ -45,10 +44,11 @@ pub fn generate(
for (handlereventname, handler) in handlerscope.handlers.iter() {
if eventname == handlereventname {
// We have a match, grab the function(s) from this scope
let fns: &Vec<Function> = match handlerscope.functions.get(&handler.functionname) {
Some(res) => Ok(res),
None => Err("Somehow unable to find function for handler"),
}?;
let fns: &Vec<Function> =
match handlerscope.functions.get(&handler.functionname) {
Some(res) => Ok(res),
None => Err("Somehow unable to find function for handler"),
}?;
// Determine the correct function from the vector by finding the last one
// that implements the correct interface (if the event has an argument,
// then exactly one argument of the same type and no return type, if no
Expand All @@ -61,19 +61,21 @@ pub fn generate(
match expected_arg_type {
None => {
if possible_fn.args.len() == 0 {
handler_pos = Some(i);
handler_pos = Some(i);
}
},
}
Some(ref arg_type) => {
if possible_fn.args.len() == 1 && &possible_fn.args[0].1 == arg_type {
if possible_fn.args.len() == 1
&& &possible_fn.args[0].1 == arg_type
{
handler_pos = Some(i);
}
},
}
}
}
let handler_fn = match handler_pos {
None => Err("No function properly matches the event signature"),
Some(i) => Ok(&fns[i]),
None => Err("No function properly matches the event signature"),
Some(i) => Ok(&fns[i]),
}?;
// Because of what we validated above, we *know* that if this event takes
// an argument, then the first microstatement is an Arg microstatement that
Expand All @@ -84,9 +86,10 @@ pub fn generate(
Microstatement::Arg { name, .. } => {
// TODO: guard against valid alan variable names that are no valid
// rust variable names
out = format!("{} let {} = arg.clone();\n", out, name).to_string();
},
_ => {},
out = format!("{} let {} = arg.clone();\n", out, name)
.to_string();
}
_ => {}
}
// Now we generate the thread to run this event handler on
out = format!("{} std::thread::spawn(move || {{\n", out).to_string();
Expand All @@ -101,7 +104,8 @@ pub fn generate(
} else {
// Inline the microstatements if it's an Alan function
for microstatement in &handler_fn.microstatements {
let stmt = from_microstatement(microstatement, handlerscope, program)?;
let stmt =
from_microstatement(microstatement, handlerscope, program)?;
if stmt != "" {
out = format!("{} {};\n", out, stmt);
}
Expand Down
20 changes: 12 additions & 8 deletions src/lntors/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,12 @@ pub fn from_microstatement(
from_microstatement(value, scope, program)?
)
.to_string()),
Microstatement::Value { typen, representation} => match typen.as_str() {
Microstatement::Value {
typen,
representation,
} => match typen.as_str() {
"String" => Ok(format!("{}.to_string()", representation).to_string()),
_ => Ok(representation.clone())
_ => Ok(representation.clone()),
},
Microstatement::FnCall { function, args } => {
let mut arg_types = Vec::new();
Expand Down Expand Up @@ -49,12 +52,13 @@ pub fn from_microstatement(
None => Ok("return".to_string()),
},
Microstatement::Emit { event, value } => match value {
Some(val) => {
Ok(format!("event::{}({})", event, from_microstatement(val, scope, program)?).to_string())
}
None => {
Ok(format!("event::{}()", event).to_string())
}
Some(val) => Ok(format!(
"event::{}({})",
event,
from_microstatement(val, scope, program)?
)
.to_string()),
None => Ok(format!("event::{}()", event).to_string()),
},
}
}
Expand Down
23 changes: 21 additions & 2 deletions src/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -823,7 +823,11 @@ impl BaseAssignable {
BaseAssignable::ObjectLiterals(_ol) => "todo".to_string(),
BaseAssignable::Functions(_f) => "todo".to_string(),
BaseAssignable::FnCall(_fc) => "todo".to_string(),
BaseAssignable::Variable(v) => v.iter().map(|segment| segment.to_string()).collect::<Vec<String>>().join(""),
BaseAssignable::Variable(v) => v
.iter()
.map(|segment| segment.to_string())
.collect::<Vec<String>>()
.join(""),
BaseAssignable::Constants(c) => c.to_string(),
}
}
Expand Down Expand Up @@ -1220,7 +1224,7 @@ named_and!(fntoop: FnToOp =>
a: String as blank,
asn: String as asn,
b: String as blank,
operators: String as operators,
operator: String as operators,
);
named_and!(opprecedence: OpPrecedence =>
precedence: String as precedence,
Expand All @@ -1246,10 +1250,25 @@ named_or!(opmap: OpMap =>
FnOpPrecedence: FnOpPrecedence as fnopprecedence,
PrecedenceFnOp: PrecedenceFnOp as precedencefnop,
);
impl OpMap {
pub fn get_fntoop(&self) -> &FnToOp {
match self {
OpMap::FnOpPrecedence(fop) => &fop.fntoop,
OpMap::PrecedenceFnOp(pfo) => &pfo.fntoop,
}
}
pub fn get_opprecedence(&self) -> &OpPrecedence {
match self {
OpMap::FnOpPrecedence(fop) => &fop.opprecedence,
OpMap::PrecedenceFnOp(pfo) => &pfo.opprecedence,
}
}
}
named_and!(operatormapping: OperatorMapping =>
fix: Fix as fix,
blank: String as blank,
opmap: OpMap as opmap,
optsemicolon: String as optsemicolon,
);
named_and!(events: Events =>
event: String as event,
Expand Down
Loading

0 comments on commit 0d95d50

Please sign in to comment.