backtraced errors and primitive funcs
This commit is contained in:
parent
ad06f7f616
commit
b9488506ce
9 changed files with 174 additions and 54 deletions
2
Makefile
2
Makefile
|
|
@ -12,7 +12,7 @@ test:
|
||||||
|
|
||||||
.PHONY: run
|
.PHONY: run
|
||||||
run:
|
run:
|
||||||
cargo run -- game.ayin
|
RUST_BACKTRACE=1 cargo run -- game.ayin
|
||||||
|
|
||||||
.PHONY: review
|
.PHONY: review
|
||||||
review:
|
review:
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,8 @@ let update = fn(state, input) {
|
||||||
return state;
|
return state;
|
||||||
};
|
};
|
||||||
|
|
||||||
let draw = fn(frame, state) {
|
let draw = fn(state) {
|
||||||
frame.clear(0,0,0);
|
frame_clear(0,0,0);
|
||||||
};
|
};
|
||||||
|
|
||||||
let migrate = fn(state) {
|
let migrate = fn(state) {
|
||||||
|
|
|
||||||
|
|
@ -71,6 +71,7 @@ pub enum Value {
|
||||||
Label(Label),
|
Label(Label),
|
||||||
Ref(Ref),
|
Ref(Ref),
|
||||||
Closure { env: EnvName, expr: Box<Expr> },
|
Closure { env: EnvName, expr: Box<Expr> },
|
||||||
|
PrimitiveFunc(Name),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A mutable variable.
|
/// A mutable variable.
|
||||||
|
|
@ -91,7 +92,7 @@ pub struct Arg {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A symbol.
|
/// A symbol.
|
||||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Clone)]
|
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone)]
|
||||||
pub struct Name(pub String);
|
pub struct Name(pub String);
|
||||||
|
|
||||||
/// A field.
|
/// A field.
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
//! Interpreter for Ayin.
|
//! Interpreter for Ayin.
|
||||||
|
|
||||||
use super::types::*;
|
use super::types::*;
|
||||||
|
use std::backtrace::Backtrace;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use crate::ast;
|
use crate::ast;
|
||||||
|
|
@ -9,8 +10,8 @@ pub fn global_env_name() -> ast::EnvName {
|
||||||
ast::EnvName("global".to_string())
|
ast::EnvName("global".to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setup(program: ast::Program) -> Result<State, Error> {
|
pub fn setup(program: ast::Program, prim_funcs: PrimitiveFuncs) -> Result<State, Error> {
|
||||||
let mut state = State::new(global_env_name().0.clone());
|
let mut state = State::new(global_env_name().0.clone(), prim_funcs);
|
||||||
|
|
||||||
defs_to_env(program.0, &global_env_name(), &mut state)?;
|
defs_to_env(program.0, &global_env_name(), &mut state)?;
|
||||||
Ok(state)
|
Ok(state)
|
||||||
|
|
@ -39,7 +40,7 @@ pub fn run(
|
||||||
func: ast::Name,
|
func: ast::Name,
|
||||||
args: Vec<ast::Expr>,
|
args: Vec<ast::Expr>,
|
||||||
) -> Result<ast::Value, Error> {
|
) -> Result<ast::Value, Error> {
|
||||||
let mut state = setup(program)?;
|
let mut state = setup(program, PrimitiveFuncs::new(vec![]))?;
|
||||||
interpret(&mut state, func, args)
|
interpret(&mut state, func, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -89,7 +90,7 @@ fn eval_expr(expr_env: &Env, state: &mut State, expr: &ast::Expr) -> Result<ast:
|
||||||
eval_expr(expr_env, state, r#else)
|
eval_expr(expr_env, state, r#else)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
v => Err(Error::NotABoolean(v)),
|
v => Err(Error::NotABoolean(v, Backtrace::capture())),
|
||||||
},
|
},
|
||||||
ast::Expr::Func(func) => {
|
ast::Expr::Func(func) => {
|
||||||
let env_name = state.generate_env(expr_env.clone())?;
|
let env_name = state.generate_env(expr_env.clone())?;
|
||||||
|
|
@ -113,12 +114,12 @@ fn eval_expr(expr_env: &Env, state: &mut State, expr: &ast::Expr) -> Result<ast:
|
||||||
})? {
|
})? {
|
||||||
Ok(last)
|
Ok(last)
|
||||||
} else {
|
} else {
|
||||||
Err(Error::LastStatementNotAnExpr)
|
Err(Error::LastStatementNotAnExpr(Backtrace::capture()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::Expr::Access { expr, field } => match eval_expr(expr_env, state, expr)? {
|
ast::Expr::Access { expr, field } => match eval_expr(expr_env, state, expr)? {
|
||||||
ast::Value::Record(record) => Ok(state.variables.get(record.get(&field)?).clone()),
|
ast::Value::Record(record) => Ok(state.variables.get(record.get(&field)?).clone()),
|
||||||
v => Err(Error::NotARecord(v)),
|
v => Err(Error::NotARecord(v, Backtrace::capture())),
|
||||||
},
|
},
|
||||||
ast::Expr::Var(var) => {
|
ast::Expr::Var(var) => {
|
||||||
let value = expr_env.get(var)?.clone();
|
let value = expr_env.get(var)?.clone();
|
||||||
|
|
@ -131,7 +132,7 @@ fn eval_expr(expr_env: &Env, state: &mut State, expr: &ast::Expr) -> Result<ast:
|
||||||
let mut closure_env: Env = state.envs.get(&env)?.clone();
|
let mut closure_env: Env = state.envs.get(&env)?.clone();
|
||||||
|
|
||||||
if func.args.len() != args.len() {
|
if func.args.len() != args.len() {
|
||||||
Err(Error::ArgumentsMismatch)?;
|
Err(Error::ArgumentsMismatch(Backtrace::capture()))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (arg, e) in func.args.into_iter().zip(args.iter()) {
|
for (arg, e) in func.args.into_iter().zip(args.iter()) {
|
||||||
|
|
@ -140,9 +141,27 @@ fn eval_expr(expr_env: &Env, state: &mut State, expr: &ast::Expr) -> Result<ast:
|
||||||
}
|
}
|
||||||
eval_expr(&closure_env, state, &func.body)
|
eval_expr(&closure_env, state, &func.body)
|
||||||
}
|
}
|
||||||
e => Err(Error::NotAFunction(e)),
|
e => Err(Error::NotAFunction(e, Backtrace::capture())),
|
||||||
},
|
},
|
||||||
e => Err(Error::NotAFunction(ast::Expr::Value(e))),
|
ast::Value::PrimitiveFunc(func) => {
|
||||||
|
let mut argsvec = vec![];
|
||||||
|
for arg in args.iter() {
|
||||||
|
let evalled = eval_expr(&expr_env, state, arg)?;
|
||||||
|
argsvec.push(evalled);
|
||||||
|
}
|
||||||
|
if let Some(func) = state.primitive_funcs.get(&func) {
|
||||||
|
Ok(func(argsvec))
|
||||||
|
} else {
|
||||||
|
Err(Error::NotAFunction(
|
||||||
|
ast::Expr::Value(ast::Value::PrimitiveFunc(func)),
|
||||||
|
Backtrace::capture(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
e => Err(Error::NotAFunction(
|
||||||
|
ast::Expr::Value(e),
|
||||||
|
Backtrace::capture(),
|
||||||
|
)),
|
||||||
},
|
},
|
||||||
ast::Expr::Value(v) => match v {
|
ast::Expr::Value(v) => match v {
|
||||||
ast::Value::Closure { expr, env } => {
|
ast::Value::Closure { expr, env } => {
|
||||||
|
|
@ -159,7 +178,7 @@ fn eval_expr(expr_env: &Env, state: &mut State, expr: &ast::Expr) -> Result<ast:
|
||||||
state.variables.set(reference, rhs.clone());
|
state.variables.set(reference, rhs.clone());
|
||||||
Ok(rhs)
|
Ok(rhs)
|
||||||
}
|
}
|
||||||
v => Err(Error::NotAReference(v.clone())),
|
v => Err(Error::NotAReference(v.clone(), Backtrace::capture())),
|
||||||
},
|
},
|
||||||
/*
|
/*
|
||||||
_ => {
|
_ => {
|
||||||
|
|
@ -200,12 +219,12 @@ fn eval_expr_shallow(
|
||||||
let result = expr_env.get(&var)?;
|
let result = expr_env.get(&var)?;
|
||||||
match result {
|
match result {
|
||||||
ast::Value::Ref(_) => Ok(result.clone()),
|
ast::Value::Ref(_) => Ok(result.clone()),
|
||||||
v => Err(Error::NotAReference(v.clone())),
|
v => Err(Error::NotAReference(v.clone(), Backtrace::capture())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::Expr::Access { expr, field } => match eval_expr(expr_env, state, expr)? {
|
ast::Expr::Access { expr, field } => match eval_expr(expr_env, state, expr)? {
|
||||||
ast::Value::Record(record) => Ok(ast::Value::Ref(record.get(&field)?.clone())),
|
ast::Value::Record(record) => Ok(ast::Value::Ref(record.get(&field)?.clone())),
|
||||||
v => Err(Error::NotARecord(v)),
|
v => Err(Error::NotARecord(v, Backtrace::capture())),
|
||||||
},
|
},
|
||||||
_ => eval_expr(expr_env, state, expr),
|
_ => eval_expr(expr_env, state, expr),
|
||||||
}
|
}
|
||||||
|
|
@ -385,7 +404,10 @@ mod tests {
|
||||||
]
|
]
|
||||||
.into();
|
.into();
|
||||||
let result = run(program, "main".into(), vec![]);
|
let result = run(program, "main".into(), vec![]);
|
||||||
assert_eq!(result, Err(Error::DuplicateNames("main".into())));
|
assert_eq!(
|
||||||
|
result,
|
||||||
|
Err(Error::DuplicateNames("main".into(), Backtrace::capture()))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
@ -396,7 +418,10 @@ mod tests {
|
||||||
]
|
]
|
||||||
.into();
|
.into();
|
||||||
let result = run(program, "main".into(), vec![]);
|
let result = run(program, "main".into(), vec![]);
|
||||||
assert_eq!(result, Err(Error::NotARecord(0.into())));
|
assert_eq!(
|
||||||
|
result,
|
||||||
|
Err(Error::NotARecord(0.into(), Backtrace::capture()))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn fun_call_not_a_function() {
|
fn fun_call_not_a_function() {
|
||||||
|
|
@ -406,6 +431,9 @@ mod tests {
|
||||||
]
|
]
|
||||||
.into();
|
.into();
|
||||||
let result = run(program, "main".into(), vec![]);
|
let result = run(program, "main".into(), vec![]);
|
||||||
assert_eq!(result, Err(Error::NotAFunction(0.into())));
|
assert_eq!(
|
||||||
|
result,
|
||||||
|
Err(Error::NotAFunction(0.into(), Backtrace::capture()))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,39 +1,73 @@
|
||||||
//! Types used in the interpreter.
|
//! Types used in the interpreter.
|
||||||
|
|
||||||
use crate::ast;
|
use crate::ast;
|
||||||
|
use std::backtrace::Backtrace;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
#[derive(PartialEq, Debug, thiserror::Error)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
#[error("Closure generation failed. Duplicate env names: {0:?}")]
|
DuplicateEnvNames(ast::EnvName, Backtrace),
|
||||||
DuplicateEnvNames(ast::EnvName),
|
DuplicateNames(ast::Name, Backtrace),
|
||||||
#[error("Duplicate names: {0:?}")]
|
NameNotFound(ast::Name, Backtrace),
|
||||||
DuplicateNames(ast::Name),
|
FieldNotFound(ast::Label, Backtrace),
|
||||||
#[error("Name not found: {0:?}")]
|
EnvNotFound(ast::EnvName, Backtrace),
|
||||||
NameNotFound(ast::Name),
|
LastStatementNotAnExpr(Backtrace),
|
||||||
#[error("Field not found: {0:?}")]
|
NotAFunction(ast::Expr, Backtrace),
|
||||||
FieldNotFound(ast::Label),
|
NotARecord(ast::Value, Backtrace),
|
||||||
#[error("Env not found: {0:?}")]
|
NotAReference(ast::Value, Backtrace),
|
||||||
EnvNotFound(ast::EnvName),
|
NotABoolean(ast::Value, Backtrace),
|
||||||
#[error("Last statement is not an expression")]
|
ArgumentsMismatch(Backtrace),
|
||||||
LastStatementNotAnExpr,
|
}
|
||||||
#[error("Not a function {0:?}")]
|
impl PartialEq for Error {
|
||||||
NotAFunction(ast::Expr),
|
fn eq(&self, other: &Self) -> bool {
|
||||||
#[error("Not a record {0:?}")]
|
match (self, other) {
|
||||||
NotARecord(ast::Value),
|
(Error::DuplicateEnvNames(a1, _), Error::DuplicateEnvNames(a2, _)) => a1 == a2,
|
||||||
#[error("Not a reference {0:?}")]
|
(Error::DuplicateNames(a1, _), Error::DuplicateNames(a2, _)) => a1 == a2,
|
||||||
NotAReference(ast::Value),
|
(Error::NameNotFound(a1, _), Error::NameNotFound(a2, _)) => a1 == a2,
|
||||||
#[error("Not a boolean {0:?}")]
|
(Error::FieldNotFound(a1, _), Error::FieldNotFound(a2, _)) => a1 == a2,
|
||||||
NotABoolean(ast::Value),
|
(Error::EnvNotFound(a1, _), Error::EnvNotFound(a2, _)) => a1 == a2,
|
||||||
#[error("Arguments mismatch")]
|
(Error::LastStatementNotAnExpr(_), Error::LastStatementNotAnExpr(_)) => true,
|
||||||
ArgumentsMismatch,
|
|
||||||
|
(Error::NotAFunction(a1, _), Error::NotAFunction(a2, _)) => a1 == a2,
|
||||||
|
(Error::NotARecord(a1, _), Error::NotARecord(a2, _)) => a1 == a2,
|
||||||
|
(Error::NotAReference(a1, _), Error::NotAReference(a2, _)) => a1 == a2,
|
||||||
|
(Error::NotABoolean(a1, _), Error::NotABoolean(a2, _)) => a1 == a2,
|
||||||
|
(Error::ArgumentsMismatch(_), Error::ArgumentsMismatch(_)) => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for Error {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Error::DuplicateEnvNames(a, b) => {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"Closure generation failed. Duplicate env names: {a:?}\n{b}"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Error::DuplicateNames(a, b) => write!(f, "Duplicate names: {a:?}\n{b}"),
|
||||||
|
Error::NameNotFound(a, b) => write!(f, "Name not found: {a:?}\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) => {
|
||||||
|
write!(f, "Last statement is not an expression\n{a}")
|
||||||
|
}
|
||||||
|
Error::NotAFunction(a, b) => write!(f, "Not a function {a:?}\n{b}"),
|
||||||
|
Error::NotARecord(a, b) => write!(f, "Not a record {a:?}\n{b}"),
|
||||||
|
Error::NotAReference(a, b) => write!(f, "Not a reference {a:?}\n{b}"),
|
||||||
|
Error::NotABoolean(a, b) => write!(f, "Not a boolean {a:?}\n{b}"),
|
||||||
|
Error::ArgumentsMismatch(a) => write!(f, "Arguments mismatch\n{a}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ast::Error> for Error {
|
impl From<ast::Error> for Error {
|
||||||
fn from(error: ast::Error) -> Error {
|
fn from(error: ast::Error) -> Error {
|
||||||
match error {
|
match error {
|
||||||
ast::Error::LabelNotFound(l) => Error::FieldNotFound(l),
|
ast::Error::LabelNotFound(l) => Error::FieldNotFound(l, Backtrace::capture()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -57,6 +91,26 @@ pub struct State {
|
||||||
env_namer: Namer,
|
env_namer: Namer,
|
||||||
pub envs: Envs,
|
pub envs: Envs,
|
||||||
pub variables: Variables,
|
pub variables: Variables,
|
||||||
|
pub primitive_funcs: PrimitiveFuncs,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct PrimitiveFuncs {
|
||||||
|
pub map: HashMap<ast::Name, PrimFunc>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type PrimFunc = fn(Vec<ast::Value>) -> ast::Value;
|
||||||
|
|
||||||
|
impl PrimitiveFuncs {
|
||||||
|
pub fn new(prims: Vec<(&str, PrimFunc)>) -> Self {
|
||||||
|
let mut map: HashMap<ast::Name, PrimFunc> = HashMap::new();
|
||||||
|
for (key, func) in prims.into_iter() {
|
||||||
|
map.insert(key.into(), func);
|
||||||
|
}
|
||||||
|
PrimitiveFuncs { map }
|
||||||
|
}
|
||||||
|
pub fn get(&self, name: &ast::Name) -> Option<&PrimFunc> {
|
||||||
|
self.map.get(name)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Variables {
|
pub struct Variables {
|
||||||
|
|
@ -84,12 +138,13 @@ impl Variables {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl State {
|
impl State {
|
||||||
pub fn new(name: String) -> State {
|
pub fn new(name: String, primitive_funcs: PrimitiveFuncs) -> State {
|
||||||
State {
|
State {
|
||||||
name,
|
name,
|
||||||
env_namer: Namer::new(),
|
env_namer: Namer::new(),
|
||||||
envs: Envs(BTreeMap::new()),
|
envs: Envs(BTreeMap::new()),
|
||||||
variables: Variables::new(),
|
variables: Variables::new(),
|
||||||
|
primitive_funcs,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn generate_env(&mut self, env: Env) -> Result<ast::EnvName, Error> {
|
pub fn generate_env(&mut self, env: Env) -> Result<ast::EnvName, Error> {
|
||||||
|
|
@ -113,14 +168,16 @@ impl Env {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn get(&self, name: &ast::Name) -> Result<&ast::Value, Error> {
|
pub fn get(&self, name: &ast::Name) -> Result<&ast::Value, Error> {
|
||||||
self.env.get(name).ok_or(Error::NameNotFound(name.clone()))
|
self.env
|
||||||
|
.get(name)
|
||||||
|
.ok_or(Error::NameNotFound(name.clone(), Backtrace::capture()))
|
||||||
}
|
}
|
||||||
pub fn insert(&mut self, name: ast::Name, value: ast::Value) {
|
pub fn insert(&mut self, name: ast::Name, value: ast::Value) {
|
||||||
self.env.insert(name.clone(), value);
|
self.env.insert(name.clone(), value);
|
||||||
}
|
}
|
||||||
pub fn insert_nodup(&mut self, name: &ast::Name, value: ast::Value) -> Result<(), Error> {
|
pub fn insert_nodup(&mut self, name: &ast::Name, value: ast::Value) -> Result<(), Error> {
|
||||||
if self.env.insert(name.clone(), value).is_some() {
|
if self.env.insert(name.clone(), value).is_some() {
|
||||||
Err(Error::DuplicateNames(name.clone()))
|
Err(Error::DuplicateNames(name.clone(), Backtrace::capture()))
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -134,16 +191,16 @@ impl Envs {
|
||||||
pub fn get(&self, env_name: &ast::EnvName) -> Result<&Env, Error> {
|
pub fn get(&self, env_name: &ast::EnvName) -> Result<&Env, Error> {
|
||||||
self.0
|
self.0
|
||||||
.get(env_name)
|
.get(env_name)
|
||||||
.ok_or(Error::EnvNotFound(env_name.clone()))
|
.ok_or(Error::EnvNotFound(env_name.clone(), Backtrace::capture()))
|
||||||
}
|
}
|
||||||
pub fn get_mut(&mut self, env_name: &ast::EnvName) -> Result<&mut Env, Error> {
|
pub fn get_mut(&mut self, env_name: &ast::EnvName) -> Result<&mut Env, Error> {
|
||||||
self.0
|
self.0
|
||||||
.get_mut(env_name)
|
.get_mut(env_name)
|
||||||
.ok_or(Error::EnvNotFound(env_name.clone()))
|
.ok_or(Error::EnvNotFound(env_name.clone(), Backtrace::capture()))
|
||||||
}
|
}
|
||||||
pub fn insert(&mut self, name: &ast::EnvName, env: Env) -> Result<(), Error> {
|
pub fn insert(&mut self, name: &ast::EnvName, env: Env) -> Result<(), Error> {
|
||||||
if self.0.insert(name.clone(), env).is_some() {
|
if self.0.insert(name.clone(), env).is_some() {
|
||||||
Err(Error::DuplicateEnvNames(name.clone()))
|
Err(Error::DuplicateEnvNames(name.clone(), Backtrace::capture()))
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ async fn main() {
|
||||||
loop {
|
loop {
|
||||||
let events = fetch_events(&mut state);
|
let events = fetch_events(&mut state);
|
||||||
update(&mut state, events);
|
update(&mut state, events);
|
||||||
draw(&state);
|
draw(&mut state);
|
||||||
next_frame().await;
|
next_frame().await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
pub mod primitive_functions;
|
||||||
|
|
||||||
pub mod runtime;
|
pub mod runtime;
|
||||||
pub use runtime::*;
|
pub use runtime::*;
|
||||||
|
|
||||||
|
|
|
||||||
22
src/runtime/primitive_functions.rs
Normal file
22
src/runtime/primitive_functions.rs
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
use crate::ast;
|
||||||
|
use crate::interpret::PrimitiveFuncs;
|
||||||
|
use macroquad::prelude::*;
|
||||||
|
|
||||||
|
pub fn primitive_funcs() -> PrimitiveFuncs {
|
||||||
|
PrimitiveFuncs::new(vec![("frame_clear", clear)])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clear(args: Vec<ast::Value>) -> ast::Value {
|
||||||
|
let r = to_u32(args.get(0));
|
||||||
|
let g = to_u32(args.get(1));
|
||||||
|
let b = to_u32(args.get(2));
|
||||||
|
clear_background(Color::from_rgba(r, g, b, 255));
|
||||||
|
ast::UNIT_VALUE
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_u32(value: Option<&ast::Value>) -> u8 {
|
||||||
|
match value {
|
||||||
|
Some(ast::Value::Int(i)) => *i as u8,
|
||||||
|
_ => 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
use super::primitive_functions::primitive_funcs;
|
||||||
use super::types::*;
|
use super::types::*;
|
||||||
use crate::ast;
|
use crate::ast;
|
||||||
use crate::ast::helpers;
|
use crate::ast::helpers;
|
||||||
|
|
@ -8,11 +9,11 @@ use macroquad::prelude::*;
|
||||||
pub async fn setup(code: ast::Program) -> State {
|
pub async fn setup(code: ast::Program) -> State {
|
||||||
let font = load_ttf_font("./assets/fonts/monogram.ttf").await.unwrap();
|
let font = load_ttf_font("./assets/fonts/monogram.ttf").await.unwrap();
|
||||||
|
|
||||||
let mut state = match interpret::setup(code) {
|
let mut state = match interpret::setup(code, primitive_funcs()) {
|
||||||
Ok(state) => state,
|
Ok(state) => state,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
println!("Error: {}", err);
|
println!("Error: {}", err);
|
||||||
interpret::State::new("game".into())
|
interpret::State::new("game".into(), primitive_funcs())
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let game_state = match interpret::interpret(&mut state, "setup".into(), vec![]) {
|
let game_state = match interpret::interpret(&mut state, "setup".into(), vec![]) {
|
||||||
|
|
@ -32,7 +33,7 @@ pub async fn setup(code: ast::Program) -> State {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn migrate(mut state: State, code: ast::Program) -> State {
|
pub async fn migrate(mut state: State, code: ast::Program) -> State {
|
||||||
match interpret::setup(code) {
|
match interpret::setup(code, primitive_funcs()) {
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
println!("Error: {}", err);
|
println!("Error: {}", err);
|
||||||
state
|
state
|
||||||
|
|
@ -136,7 +137,7 @@ pub fn fetch_events(state: &mut State) -> Input {
|
||||||
input
|
input
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw(state: &State) {
|
pub fn draw(state: &mut State) {
|
||||||
clear_background(Color::from_hex(0x081829));
|
clear_background(Color::from_hex(0x081829));
|
||||||
|
|
||||||
set_default_camera();
|
set_default_camera();
|
||||||
|
|
@ -151,6 +152,15 @@ pub fn draw(state: &State) {
|
||||||
|
|
||||||
set_default_camera();
|
set_default_camera();
|
||||||
|
|
||||||
|
match interpret::interpret(
|
||||||
|
&mut state.state,
|
||||||
|
"draw".into(),
|
||||||
|
vec![ast::Expr::Value(state.game_state.clone())],
|
||||||
|
) {
|
||||||
|
Ok(_) => {}
|
||||||
|
Err(err) => println!("Error: {}", err),
|
||||||
|
}
|
||||||
|
|
||||||
println!(
|
println!(
|
||||||
"{:#?}",
|
"{:#?}",
|
||||||
interpret::value_to_stadnalone_expr(&state.state, state.game_state.clone())
|
interpret::value_to_stadnalone_expr(&state.state, state.game_state.clone())
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue