many fixes and full program tests

This commit is contained in:
me 2025-12-20 17:36:24 +02:00
parent 0abada448b
commit 7302265436
11 changed files with 159 additions and 26 deletions

View file

@ -1,23 +1,42 @@
let min = 40
let max = 101
let speed = 60 # how many degrees in a second
let setup = fn() {
return {
.color: {
.r: 0,
.g: 0,
.b: 0,
}
},
.dir: 1,
};
};
}
let update = fn(state, input) {
state.color.g = state.color.g + (random_u8() % 3) % 50;
state.color.b = (state.color.b + 1) % 255;
let dir = state.dir * speed * get_frame_time();
state.color.g = random_u8() % 1;
state.color.r = (state.color.r + dir) % max;
if state.color.r < min {
state.color.r = min;
};
state.dir =
if state.color.r >= (max - 1) {
-1
} else {
if state.color.r <= min {
1
} else {
state.dir
}
};
return state;
};
}
let draw = fn(state) {
frame_clear(state.color.r, state.color.g, state.color.b);
};
}
let migrate = fn(state) {
return { .player: { .pos: state.player.position } };
};
}

View file

@ -39,9 +39,10 @@ pub fn run(
program: ast::Program,
func: ast::Name,
args: Vec<ast::Expr>,
) -> Result<ast::Value, Error> {
) -> Result<ast::Expr, Error> {
let mut state = setup(program, PrimitiveFuncs::new(vec![]))?;
interpret(&mut state, func, args)
let value = interpret(&mut state, func, args)?;
Ok(value_to_stadnalone_expr(&state, value).unwrap())
}
enum StatementResult {
@ -153,7 +154,7 @@ fn eval_expr(expr_env: &Env, state: &mut State, expr: &ast::Expr) -> Result<ast:
}
for (arg, e) in func.args.into_iter().zip(args.iter()) {
let evalled = eval_expr(&closure_env, state, e)?;
let evalled = eval_expr(&expr_env, state, e)?;
closure_env.insert(arg.name, evalled);
}
match eval_expr(&closure_env, state, &func.body)? {
@ -272,6 +273,28 @@ fn eval_expr(expr_env: &Env, state: &mut State, expr: &ast::Expr) -> Result<ast:
};
Ok(ast::Value::Boolean(cop(a, b)))
}
(ast::Value::Int(a), ast::Value::Float(b)) => {
let cop = match cop {
ast::Cmp::Eq => |a, b| a == b,
ast::Cmp::NotEq => |a, b| a != b,
ast::Cmp::Gt => |a, b| a > b,
ast::Cmp::Gte => |a, b| a >= b,
ast::Cmp::Lt => |a, b| a < b,
ast::Cmp::Lte => |a, b| a <= b,
};
Ok(ast::Value::Boolean(cop(a as f32, b)))
}
(ast::Value::Float(a), ast::Value::Int(b)) => {
let cop = match cop {
ast::Cmp::Eq => |a, b| a == b,
ast::Cmp::NotEq => |a, b| a != b,
ast::Cmp::Gt => |a, b| a > b,
ast::Cmp::Gte => |a, b| a >= b,
ast::Cmp::Lt => |a, b| a < b,
ast::Cmp::Lte => |a, b| a <= b,
};
Ok(ast::Value::Boolean(cop(a, b as f32)))
}
(ast::Value::Float(a), ast::Value::Float(b)) => {
let cop = match cop {
ast::Cmp::Eq => |a, b| a == b,

View file

@ -9,7 +9,7 @@ use std::collections::HashMap;
pub enum Error {
DuplicateEnvNames(ast::EnvName, Backtrace),
DuplicateNames(ast::Name, Backtrace),
NameNotFound(ast::Name, Backtrace),
NameNotFound(ast::Name, Env, Backtrace),
FieldNotFound(ast::Label, Backtrace),
EnvNotFound(ast::EnvName, Backtrace),
LastStatementNotAnExpr(Backtrace),
@ -25,7 +25,7 @@ impl PartialEq for Error {
match (self, other) {
(Error::DuplicateEnvNames(a1, _), Error::DuplicateEnvNames(a2, _)) => a1 == a2,
(Error::DuplicateNames(a1, _), Error::DuplicateNames(a2, _)) => a1 == a2,
(Error::NameNotFound(a1, _), Error::NameNotFound(a2, _)) => a1 == a2,
(Error::NameNotFound(a1, _, _), Error::NameNotFound(a2, _, _)) => a1 == a2,
(Error::FieldNotFound(a1, _), Error::FieldNotFound(a2, _)) => a1 == a2,
(Error::EnvNotFound(a1, _), Error::EnvNotFound(a2, _)) => a1 == a2,
(Error::LastStatementNotAnExpr(_), Error::LastStatementNotAnExpr(_)) => true,
@ -50,7 +50,7 @@ impl std::fmt::Display for Error {
)
}
Error::DuplicateNames(a, b) => write!(f, "Duplicate names: {a:?}\n{b}"),
Error::NameNotFound(a, b) => write!(f, "Name not found: {a:?}\n{b}"),
Error::NameNotFound(a, e, b) => write!(f, "Name not found: {a:?} in {e:#?}\n{b}"),
Error::FieldNotFound(a, b) => write!(f, "Field not found: {a:?}\n{b}"),
Error::EnvNotFound(a, b) => write!(f, "Env not found: {a:?}\n{b}"),
Error::LastStatementNotAnExpr(a) => {
@ -170,9 +170,14 @@ impl Env {
}
}
pub fn get(&self, name: &ast::Name) -> Result<&ast::Value, Error> {
self.env
.get(name)
.ok_or(Error::NameNotFound(name.clone(), Backtrace::capture()))
match self.env.get(name) {
None => Err(Error::NameNotFound(
name.clone(),
self.clone(),
Backtrace::capture(),
)),
Some(v) => Ok(v),
}
}
pub fn insert(&mut self, name: ast::Name, value: ast::Value) {
self.env.insert(name.clone(), value);

View file

@ -3,7 +3,7 @@ pub mod interpret;
pub mod parser;
pub mod runtime;
pub fn run_main(code: &str) -> Result<ast::Value, String> {
pub fn run_main(code: &str) -> Result<ast::Expr, String> {
match parser::parse_file(code.into()) {
Err(err) => Err(format!("Error: {err:?}")),
Ok(program) => match interpret::run(program, "main".into(), vec![]) {
@ -63,6 +63,43 @@ let main = fn() {
};
return a;
}
";
let result = run_main(program);
insta::assert_debug_snapshot!(result);
}
#[test]
fn direction() {
let program = "
let main = fn() {
let state = setup();
update(state)
}
let setup = fn() {
return {
.color: {
.b: 254,
},
.dir: 1,
};
}
let update = fn(state) {
state.color.b = (state.color.b + state.dir) % 256;
state.dir =
if state.color.b == 255 {
-1
} else {
if state.color.b == 0 {
1
} else {
state.dir
}
};
return state;
}
";
let result = run_main(program);
insta::assert_debug_snapshot!(result);

View file

@ -1,3 +1,4 @@
use macroquad::time::get_frame_time;
use rand::prelude::*;
use crate::ast;
@ -5,7 +6,11 @@ use crate::interpret::PrimitiveFuncs;
use macroquad::prelude as mq;
pub fn primitive_funcs() -> PrimitiveFuncs {
PrimitiveFuncs::new(vec![("frame_clear", clear), ("random_u8", random_u8)])
PrimitiveFuncs::new(vec![
("frame_clear", clear),
("get_frame_time", frame_time),
("random_u8", random_u8),
])
}
fn clear(args: Vec<ast::Value>) -> ast::Value {
@ -19,6 +24,7 @@ fn clear(args: Vec<ast::Value>) -> ast::Value {
fn to_u32(value: Option<&ast::Value>) -> u8 {
match value {
Some(ast::Value::Int(i)) => *i as u8,
Some(ast::Value::Float(f)) => *f as u8,
_ => 0,
}
}
@ -27,3 +33,7 @@ fn random_u8(_args: Vec<ast::Value>) -> ast::Value {
let random: u8 = rand::rng().random::<u8>();
ast::Value::Int(random as i32)
}
fn frame_time(_args: Vec<ast::Value>) -> ast::Value {
ast::Value::Float(get_frame_time() as f32)
}

View file

@ -160,6 +160,7 @@ pub fn draw(state: &mut State) {
Ok(_) => {}
Err(err) => println!("Error: {}", err),
}
draw_fps();
/*
println!(

View file

@ -3,7 +3,9 @@ source: src/lib.rs
expression: result
---
Ok(
Value(
Int(
4,
),
),
)

View file

@ -0,0 +1,30 @@
---
source: src/lib.rs
expression: result
---
Ok(
Record(
{
Label(
"color",
): Record(
{
Label(
"b",
): Value(
Int(
255,
),
),
},
),
Label(
"dir",
): Value(
Int(
-1,
),
),
},
),
)

View file

@ -3,7 +3,9 @@ source: src/lib.rs
expression: result
---
Ok(
Value(
Int(
108,
),
),
)

View file

@ -3,7 +3,9 @@ source: src/lib.rs
expression: result
---
Ok(
Value(
Int(
3,
),
),
)

View file

@ -3,7 +3,9 @@ source: src/lib.rs
expression: result
---
Ok(
Value(
Int(
4,
),
),
)