string keys on dicts now fully work
This commit is contained in:
parent
659fdd3506
commit
9f9f59b33b
|
@ -17,3 +17,4 @@ wasm-bindgen-futures = "0.4.50"
|
||||||
serde = {version = "1.0", features = ["derive"]}
|
serde = {version = "1.0", features = ["derive"]}
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
console_error_panic_hook = "0.1.7"
|
console_error_panic_hook = "0.1.7"
|
||||||
|
struct_scalpel = "0.1.1"
|
||||||
|
|
|
@ -879,6 +879,12 @@ fn get {
|
||||||
nil -> default
|
nil -> default
|
||||||
val -> val
|
val -> val
|
||||||
}
|
}
|
||||||
|
(k as :string) -> get (k, _)
|
||||||
|
(k as :string, d as :dict) -> base :get (d, k)
|
||||||
|
(k as :string, d as :dict, default) -> match base :get (d, k) with {
|
||||||
|
nil -> default
|
||||||
|
val -> val
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update {
|
fn update {
|
||||||
|
|
4
pkg/rudus.d.ts
vendored
4
pkg/rudus.d.ts
vendored
|
@ -14,8 +14,8 @@ export interface InitOutput {
|
||||||
readonly __wbindgen_malloc: (a: number, b: number) => number;
|
readonly __wbindgen_malloc: (a: number, b: number) => number;
|
||||||
readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
|
readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
|
||||||
readonly __wbindgen_export_6: WebAssembly.Table;
|
readonly __wbindgen_export_6: WebAssembly.Table;
|
||||||
readonly closure346_externref_shim: (a: number, b: number, c: any) => void;
|
readonly closure347_externref_shim: (a: number, b: number, c: any) => void;
|
||||||
readonly closure370_externref_shim: (a: number, b: number, c: any, d: any) => void;
|
readonly closure371_externref_shim: (a: number, b: number, c: any, d: any) => void;
|
||||||
readonly __wbindgen_start: () => void;
|
readonly __wbindgen_start: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -240,13 +240,13 @@ function _assertNum(n) {
|
||||||
function __wbg_adapter_20(arg0, arg1, arg2) {
|
function __wbg_adapter_20(arg0, arg1, arg2) {
|
||||||
_assertNum(arg0);
|
_assertNum(arg0);
|
||||||
_assertNum(arg1);
|
_assertNum(arg1);
|
||||||
wasm.closure346_externref_shim(arg0, arg1, arg2);
|
wasm.closure347_externref_shim(arg0, arg1, arg2);
|
||||||
}
|
}
|
||||||
|
|
||||||
function __wbg_adapter_50(arg0, arg1, arg2, arg3) {
|
function __wbg_adapter_50(arg0, arg1, arg2, arg3) {
|
||||||
_assertNum(arg0);
|
_assertNum(arg0);
|
||||||
_assertNum(arg1);
|
_assertNum(arg1);
|
||||||
wasm.closure370_externref_shim(arg0, arg1, arg2, arg3);
|
wasm.closure371_externref_shim(arg0, arg1, arg2, arg3);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function __wbg_load(module, imports) {
|
async function __wbg_load(module, imports) {
|
||||||
|
@ -425,8 +425,8 @@ function __wbg_get_imports() {
|
||||||
_assertBoolean(ret);
|
_assertBoolean(ret);
|
||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
imports.wbg.__wbindgen_closure_wrapper7819 = function() { return logError(function (arg0, arg1, arg2) {
|
imports.wbg.__wbindgen_closure_wrapper7945 = function() { return logError(function (arg0, arg1, arg2) {
|
||||||
const ret = makeMutClosure(arg0, arg1, 347, __wbg_adapter_20);
|
const ret = makeMutClosure(arg0, arg1, 348, __wbg_adapter_20);
|
||||||
return ret;
|
return ret;
|
||||||
}, arguments) };
|
}, arguments) };
|
||||||
imports.wbg.__wbindgen_debug_string = function(arg0, arg1) {
|
imports.wbg.__wbindgen_debug_string = function(arg0, arg1) {
|
||||||
|
|
Binary file not shown.
4
pkg/rudus_bg.wasm.d.ts
vendored
4
pkg/rudus_bg.wasm.d.ts
vendored
|
@ -9,6 +9,6 @@ export const __wbindgen_free: (a: number, b: number, c: number) => void;
|
||||||
export const __wbindgen_malloc: (a: number, b: number) => number;
|
export const __wbindgen_malloc: (a: number, b: number) => number;
|
||||||
export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
|
export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
|
||||||
export const __wbindgen_export_6: WebAssembly.Table;
|
export const __wbindgen_export_6: WebAssembly.Table;
|
||||||
export const closure346_externref_shim: (a: number, b: number, c: any) => void;
|
export const closure347_externref_shim: (a: number, b: number, c: any) => void;
|
||||||
export const closure370_externref_shim: (a: number, b: number, c: any, d: any) => void;
|
export const closure371_externref_shim: (a: number, b: number, c: any, d: any) => void;
|
||||||
export const __wbindgen_start: () => void;
|
export const __wbindgen_start: () => void;
|
||||||
|
|
23
src/ast.rs
23
src/ast.rs
|
@ -4,7 +4,7 @@ use std::fmt;
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum StringPart {
|
pub enum StringPart {
|
||||||
Data(String),
|
Data(String),
|
||||||
Word(String),
|
Word(&'static str),
|
||||||
Inline(String),
|
Inline(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,7 +63,8 @@ pub enum Ast {
|
||||||
Do(Vec<Spanned<Self>>),
|
Do(Vec<Spanned<Self>>),
|
||||||
Repeat(Box<Spanned<Self>>, Box<Spanned<Self>>),
|
Repeat(Box<Spanned<Self>>, Box<Spanned<Self>>),
|
||||||
Splat(&'static str),
|
Splat(&'static str),
|
||||||
Pair(&'static str, Box<Spanned<Self>>),
|
StringPair(&'static str, Box<Spanned<Self>>),
|
||||||
|
KeywordPair(&'static str, Box<Spanned<Self>>),
|
||||||
Loop(Box<Spanned<Self>>, Vec<Spanned<Self>>),
|
Loop(Box<Spanned<Self>>, Vec<Spanned<Self>>),
|
||||||
Recur(Vec<Spanned<Self>>),
|
Recur(Vec<Spanned<Self>>),
|
||||||
|
|
||||||
|
@ -80,7 +81,8 @@ pub enum Ast {
|
||||||
PlaceholderPattern,
|
PlaceholderPattern,
|
||||||
TuplePattern(Vec<Spanned<Self>>),
|
TuplePattern(Vec<Spanned<Self>>),
|
||||||
ListPattern(Vec<Spanned<Self>>),
|
ListPattern(Vec<Spanned<Self>>),
|
||||||
PairPattern(&'static str, Box<Spanned<Self>>),
|
StrPairPattern(&'static str, Box<Spanned<Self>>),
|
||||||
|
KeyPairPattern(&'static str, Box<Spanned<Self>>),
|
||||||
DictPattern(Vec<Spanned<Self>>),
|
DictPattern(Vec<Spanned<Self>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,7 +214,12 @@ impl Ast {
|
||||||
Splat(word) => format!("...{}", word),
|
Splat(word) => format!("...{}", word),
|
||||||
Splattern(pattern) => format!("...{}", pattern.0.show()),
|
Splattern(pattern) => format!("...{}", pattern.0.show()),
|
||||||
AsPattern(word, type_keyword) => format!("{word} as :{type_keyword}"),
|
AsPattern(word, type_keyword) => format!("{word} as :{type_keyword}"),
|
||||||
Pair(key, value) | PairPattern(key, value) => format!(":{key} {}", value.0.show()),
|
KeywordPair(key, value) | KeyPairPattern(key, value) => {
|
||||||
|
format!(":{key} {}", value.0.show())
|
||||||
|
}
|
||||||
|
StringPair(key, value) | StrPairPattern(key, value) => {
|
||||||
|
format!("\"{key}\" {}", value.0.show())
|
||||||
|
}
|
||||||
Loop(init, body) => format!(
|
Loop(init, body) => format!(
|
||||||
"loop {} with {{\n {}\n}}",
|
"loop {} with {{\n {}\n}}",
|
||||||
init.0.show(),
|
init.0.show(),
|
||||||
|
@ -377,8 +384,11 @@ impl fmt::Display for Ast {
|
||||||
Splat(word) => {
|
Splat(word) => {
|
||||||
write!(f, "splat: {}", word)
|
write!(f, "splat: {}", word)
|
||||||
}
|
}
|
||||||
Pair(k, v) => {
|
KeywordPair(k, v) | KeyPairPattern(k, v) => {
|
||||||
write!(f, "pair: {} {}", k, v.0)
|
write!(f, "key_pair: {} {}", k, v.0)
|
||||||
|
}
|
||||||
|
StringPair(k, v) | StrPairPattern(k, v) => {
|
||||||
|
write!(f, "str_pair: {k} {}", v.0)
|
||||||
}
|
}
|
||||||
Loop(init, body) => {
|
Loop(init, body) => {
|
||||||
write!(
|
write!(
|
||||||
|
@ -446,7 +456,6 @@ impl fmt::Display for Ast {
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join(", ")
|
.join(", ")
|
||||||
),
|
),
|
||||||
PairPattern(key, value) => write!(f, ":{} {}", key, value.0),
|
|
||||||
InterpolatedPattern(strprts) => write!(
|
InterpolatedPattern(strprts) => write!(
|
||||||
f,
|
f,
|
||||||
"interpolated: \"{}\"",
|
"interpolated: \"{}\"",
|
||||||
|
|
167
src/base.rs
167
src/base.rs
|
@ -612,64 +612,133 @@ pub fn r#mod(x: &Value, y: &Value) -> Value {
|
||||||
|
|
||||||
pub fn make_base() -> Value {
|
pub fn make_base() -> Value {
|
||||||
let members = vec![
|
let members = vec![
|
||||||
("add", Value::BaseFn(BaseFn::Binary("add", add))),
|
("add", Value::BaseFn(Box::new(BaseFn::Binary("add", add)))),
|
||||||
("append", Value::BaseFn(BaseFn::Binary("append", append))),
|
(
|
||||||
("assoc", Value::BaseFn(BaseFn::Ternary("assoc", assoc))),
|
"append",
|
||||||
("at", Value::BaseFn(BaseFn::Binary("at", at))),
|
Value::BaseFn(Box::new(BaseFn::Binary("append", append))),
|
||||||
("atan_2", Value::BaseFn(BaseFn::Binary("atan_2", atan_2))),
|
),
|
||||||
("bool", Value::BaseFn(BaseFn::Unary("bool", r#bool))),
|
(
|
||||||
("ceil", Value::BaseFn(BaseFn::Unary("ceil", ceil))),
|
"assoc",
|
||||||
("chars", Value::BaseFn(BaseFn::Unary("chars", chars))),
|
Value::BaseFn(Box::new(BaseFn::Ternary("assoc", assoc))),
|
||||||
("concat", Value::BaseFn(BaseFn::Binary("concat", concat))),
|
),
|
||||||
("cos", Value::BaseFn(BaseFn::Unary("cos", cos))),
|
("at", Value::BaseFn(Box::new(BaseFn::Binary("at", at)))),
|
||||||
("count", Value::BaseFn(BaseFn::Unary("count", count))),
|
(
|
||||||
("dec", Value::BaseFn(BaseFn::Unary("dec", dec))),
|
"atan_2",
|
||||||
("dissoc", Value::BaseFn(BaseFn::Binary("dissoc", dissoc))),
|
Value::BaseFn(Box::new(BaseFn::Binary("atan_2", atan_2))),
|
||||||
("div", Value::BaseFn(BaseFn::Binary("div", div))),
|
),
|
||||||
("doc!", Value::BaseFn(BaseFn::Unary("doc!", doc))),
|
(
|
||||||
|
"bool",
|
||||||
|
Value::BaseFn(Box::new(BaseFn::Unary("bool", r#bool))),
|
||||||
|
),
|
||||||
|
("ceil", Value::BaseFn(Box::new(BaseFn::Unary("ceil", ceil)))),
|
||||||
|
(
|
||||||
|
"chars",
|
||||||
|
Value::BaseFn(Box::new(BaseFn::Unary("chars", chars))),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"concat",
|
||||||
|
Value::BaseFn(Box::new(BaseFn::Binary("concat", concat))),
|
||||||
|
),
|
||||||
|
("cos", Value::BaseFn(Box::new(BaseFn::Unary("cos", cos)))),
|
||||||
|
(
|
||||||
|
"count",
|
||||||
|
Value::BaseFn(Box::new(BaseFn::Unary("count", count))),
|
||||||
|
),
|
||||||
|
("dec", Value::BaseFn(Box::new(BaseFn::Unary("dec", dec)))),
|
||||||
|
(
|
||||||
|
"dissoc",
|
||||||
|
Value::BaseFn(Box::new(BaseFn::Binary("dissoc", dissoc))),
|
||||||
|
),
|
||||||
|
("div", Value::BaseFn(Box::new(BaseFn::Binary("div", div)))),
|
||||||
|
("doc!", Value::BaseFn(Box::new(BaseFn::Unary("doc!", doc)))),
|
||||||
(
|
(
|
||||||
"downcase",
|
"downcase",
|
||||||
Value::BaseFn(BaseFn::Unary("downcase", downcase)),
|
Value::BaseFn(Box::new(BaseFn::Unary("downcase", downcase))),
|
||||||
|
),
|
||||||
|
("eq?", Value::BaseFn(Box::new(BaseFn::Binary("eq?", eq)))),
|
||||||
|
(
|
||||||
|
"first",
|
||||||
|
Value::BaseFn(Box::new(BaseFn::Unary("first", first))),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"floor",
|
||||||
|
Value::BaseFn(Box::new(BaseFn::Unary("floor", floor))),
|
||||||
|
),
|
||||||
|
("get", Value::BaseFn(Box::new(BaseFn::Binary("get", get)))),
|
||||||
|
("gt?", Value::BaseFn(Box::new(BaseFn::Binary("gt?", gt)))),
|
||||||
|
("gte?", Value::BaseFn(Box::new(BaseFn::Binary("gte?", gte)))),
|
||||||
|
("inc", Value::BaseFn(Box::new(BaseFn::Unary("inc", inc)))),
|
||||||
|
("last", Value::BaseFn(Box::new(BaseFn::Unary("last", last)))),
|
||||||
|
("list", Value::BaseFn(Box::new(BaseFn::Unary("list", list)))),
|
||||||
|
("lt?", Value::BaseFn(Box::new(BaseFn::Binary("lt?", lt)))),
|
||||||
|
("lte?", Value::BaseFn(Box::new(BaseFn::Binary("lte?", lte)))),
|
||||||
|
("mod", Value::BaseFn(Box::new(BaseFn::Binary("mod", r#mod)))),
|
||||||
|
(
|
||||||
|
"mult",
|
||||||
|
Value::BaseFn(Box::new(BaseFn::Binary("mult", mult))),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"number",
|
||||||
|
Value::BaseFn(Box::new(BaseFn::Unary("number", number))),
|
||||||
),
|
),
|
||||||
("eq?", Value::BaseFn(BaseFn::Binary("eq?", eq))),
|
|
||||||
("first", Value::BaseFn(BaseFn::Unary("first", first))),
|
|
||||||
("floor", Value::BaseFn(BaseFn::Unary("floor", floor))),
|
|
||||||
("get", Value::BaseFn(BaseFn::Binary("get", get))),
|
|
||||||
("gt?", Value::BaseFn(BaseFn::Binary("gt?", gt))),
|
|
||||||
("gte?", Value::BaseFn(BaseFn::Binary("gte?", gte))),
|
|
||||||
("inc", Value::BaseFn(BaseFn::Unary("inc", inc))),
|
|
||||||
("last", Value::BaseFn(BaseFn::Unary("last", last))),
|
|
||||||
("list", Value::BaseFn(BaseFn::Unary("list", list))),
|
|
||||||
("lt?", Value::BaseFn(BaseFn::Binary("lt?", lt))),
|
|
||||||
("lte?", Value::BaseFn(BaseFn::Binary("lte?", lte))),
|
|
||||||
("mod", Value::BaseFn(BaseFn::Binary("mod", r#mod))),
|
|
||||||
("mult", Value::BaseFn(BaseFn::Binary("mult", mult))),
|
|
||||||
("number", Value::BaseFn(BaseFn::Unary("number", number))),
|
|
||||||
("pi", Value::Number(std::f64::consts::PI)),
|
("pi", Value::Number(std::f64::consts::PI)),
|
||||||
("print!", Value::BaseFn(BaseFn::Unary("print!", print))),
|
(
|
||||||
|
"print!",
|
||||||
|
Value::BaseFn(Box::new(BaseFn::Unary("print!", print))),
|
||||||
|
),
|
||||||
("process", Value::Process),
|
("process", Value::Process),
|
||||||
(
|
(
|
||||||
"random",
|
"random",
|
||||||
Value::BaseFn(BaseFn::Nullary("random", base_random)),
|
Value::BaseFn(Box::new(BaseFn::Nullary("random", base_random))),
|
||||||
),
|
),
|
||||||
("range", Value::BaseFn(BaseFn::Binary("range", range))),
|
(
|
||||||
("rest", Value::BaseFn(BaseFn::Unary("rest", rest))),
|
"range",
|
||||||
("round", Value::BaseFn(BaseFn::Unary("round", round))),
|
Value::BaseFn(Box::new(BaseFn::Binary("range", range))),
|
||||||
("show", Value::BaseFn(BaseFn::Unary("show", show))),
|
),
|
||||||
("sin", Value::BaseFn(BaseFn::Unary("sin", sin))),
|
("rest", Value::BaseFn(Box::new(BaseFn::Unary("rest", rest)))),
|
||||||
("slice", Value::BaseFn(BaseFn::Ternary("slice", slice))),
|
(
|
||||||
("split", Value::BaseFn(BaseFn::Binary("split", split))),
|
"round",
|
||||||
("sqrt", Value::BaseFn(BaseFn::Unary("sqrt", sqrt))),
|
Value::BaseFn(Box::new(BaseFn::Unary("round", round))),
|
||||||
|
),
|
||||||
|
("show", Value::BaseFn(Box::new(BaseFn::Unary("show", show)))),
|
||||||
|
("sin", Value::BaseFn(Box::new(BaseFn::Unary("sin", sin)))),
|
||||||
|
(
|
||||||
|
"slice",
|
||||||
|
Value::BaseFn(Box::new(BaseFn::Ternary("slice", slice))),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"split",
|
||||||
|
Value::BaseFn(Box::new(BaseFn::Binary("split", split))),
|
||||||
|
),
|
||||||
|
("sqrt", Value::BaseFn(Box::new(BaseFn::Unary("sqrt", sqrt)))),
|
||||||
("sqrt_2", Value::Number(std::f64::consts::SQRT_2)),
|
("sqrt_2", Value::Number(std::f64::consts::SQRT_2)),
|
||||||
("store!", Value::BaseFn(BaseFn::Binary("store!", store))),
|
(
|
||||||
("sub", Value::BaseFn(BaseFn::Binary("sub", sub))),
|
"store!",
|
||||||
("tan", Value::BaseFn(BaseFn::Unary("tan", tan))),
|
Value::BaseFn(Box::new(BaseFn::Binary("store!", store))),
|
||||||
("trim", Value::BaseFn(BaseFn::Unary("trim", trim))),
|
),
|
||||||
("triml", Value::BaseFn(BaseFn::Unary("triml", triml))),
|
("sub", Value::BaseFn(Box::new(BaseFn::Binary("sub", sub)))),
|
||||||
("trimr", Value::BaseFn(BaseFn::Unary("trimr", trimr))),
|
("tan", Value::BaseFn(Box::new(BaseFn::Unary("tan", tan)))),
|
||||||
("type", Value::BaseFn(BaseFn::Unary("type", r#type))),
|
("trim", Value::BaseFn(Box::new(BaseFn::Unary("trim", trim)))),
|
||||||
("unbox", Value::BaseFn(BaseFn::Unary("unbox", unbox))),
|
(
|
||||||
("upcase", Value::BaseFn(BaseFn::Unary("upcase", upcase))),
|
"triml",
|
||||||
|
Value::BaseFn(Box::new(BaseFn::Unary("triml", triml))),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"trimr",
|
||||||
|
Value::BaseFn(Box::new(BaseFn::Unary("trimr", trimr))),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"type",
|
||||||
|
Value::BaseFn(Box::new(BaseFn::Unary("type", r#type))),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"unbox",
|
||||||
|
Value::BaseFn(Box::new(BaseFn::Unary("unbox", unbox))),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"upcase",
|
||||||
|
Value::BaseFn(Box::new(BaseFn::Unary("upcase", upcase))),
|
||||||
|
),
|
||||||
];
|
];
|
||||||
let members = members
|
let members = members
|
||||||
.iter()
|
.iter()
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
use crate::op::Op;
|
use crate::op::Op;
|
||||||
use crate::value::Value;
|
use crate::value::{Key, Value};
|
||||||
use imbl::HashMap;
|
use imbl::HashMap;
|
||||||
use num_traits::FromPrimitive;
|
use num_traits::FromPrimitive;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct StrPattern {
|
pub struct StrPattern {
|
||||||
pub words: Vec<String>,
|
pub words: Vec<&'static str>,
|
||||||
pub re: Regex,
|
pub re: Regex,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ pub struct Chunk {
|
||||||
pub bytecode: Vec<u8>,
|
pub bytecode: Vec<u8>,
|
||||||
pub keywords: Vec<&'static str>,
|
pub keywords: Vec<&'static str>,
|
||||||
pub string_patterns: Vec<StrPattern>,
|
pub string_patterns: Vec<StrPattern>,
|
||||||
pub env: HashMap<&'static str, Value>,
|
pub env: HashMap<Key, Value>,
|
||||||
pub msgs: Vec<String>,
|
pub msgs: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -101,7 +101,7 @@ impl Compiler {
|
||||||
name: &'static str,
|
name: &'static str,
|
||||||
src: &'static str,
|
src: &'static str,
|
||||||
depth: usize,
|
depth: usize,
|
||||||
env: imbl::HashMap<&'static str, Value>,
|
env: imbl::HashMap<Key, Value>,
|
||||||
debug: bool,
|
debug: bool,
|
||||||
) -> Compiler {
|
) -> Compiler {
|
||||||
let chunk = Chunk {
|
let chunk = Chunk {
|
||||||
|
@ -703,10 +703,12 @@ impl Compiler {
|
||||||
let match_depth = self.match_depth;
|
let match_depth = self.match_depth;
|
||||||
self.match_depth = 0;
|
self.match_depth = 0;
|
||||||
for pair in pairs.iter().take(pairs_len) {
|
for pair in pairs.iter().take(pairs_len) {
|
||||||
let (PairPattern(key, pattern), _) = pair else {
|
let (key, pattern) = match &pair.0 {
|
||||||
unreachable!()
|
KeyPairPattern(key, pattern) => (Value::Keyword(key), pattern),
|
||||||
|
StrPairPattern(key, pattern) => (Value::Interned(key), pattern),
|
||||||
|
_ => unreachable!("expected key to be keyword or string"),
|
||||||
};
|
};
|
||||||
self.emit_constant(Value::Keyword(key));
|
self.emit_constant(key);
|
||||||
self.emit_op(Op::LoadDictValue);
|
self.emit_op(Op::LoadDictValue);
|
||||||
self.emit_byte(dict_stack_pos);
|
self.emit_byte(dict_stack_pos);
|
||||||
self.visit(pattern);
|
self.visit(pattern);
|
||||||
|
@ -721,7 +723,7 @@ impl Compiler {
|
||||||
self.stack_depth += 1;
|
self.stack_depth += 1;
|
||||||
|
|
||||||
for pair in pairs.iter().take(pairs_len) {
|
for pair in pairs.iter().take(pairs_len) {
|
||||||
let (PairPattern(key, _), _) = pair else {
|
let (KeyPairPattern(key, _), _) = pair else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
self.emit_constant(Value::Keyword(key));
|
self.emit_constant(Value::Keyword(key));
|
||||||
|
@ -785,9 +787,8 @@ impl Compiler {
|
||||||
self.emit_byte(pattern_idx);
|
self.emit_byte(pattern_idx);
|
||||||
|
|
||||||
for word in moar_words {
|
for word in moar_words {
|
||||||
let name: &'static str = std::string::String::leak(word);
|
|
||||||
let binding = Binding {
|
let binding = Binding {
|
||||||
name,
|
name: word,
|
||||||
depth: self.scope_depth,
|
depth: self.scope_depth,
|
||||||
stack_pos: self.stack_depth,
|
stack_pos: self.stack_depth,
|
||||||
};
|
};
|
||||||
|
@ -797,7 +798,7 @@ impl Compiler {
|
||||||
|
|
||||||
self.patch_jump(jnm_idx, self.len() - jnm_idx - 3);
|
self.patch_jump(jnm_idx, self.len() - jnm_idx - 3);
|
||||||
}
|
}
|
||||||
PairPattern(_, _) => unreachable!(),
|
KeyPairPattern(..) | StrPairPattern(..) => unreachable!(),
|
||||||
Tuple(members) => {
|
Tuple(members) => {
|
||||||
self.tail_pos = false;
|
self.tail_pos = false;
|
||||||
for member in members {
|
for member in members {
|
||||||
|
@ -842,7 +843,12 @@ impl Compiler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Pair(key, value) => {
|
StringPair(key, value) => {
|
||||||
|
self.tail_pos = false;
|
||||||
|
self.emit_constant(Value::Interned(key));
|
||||||
|
self.visit(value);
|
||||||
|
}
|
||||||
|
KeywordPair(key, value) => {
|
||||||
self.tail_pos = false;
|
self.tail_pos = false;
|
||||||
self.emit_constant(Value::Keyword(key));
|
self.emit_constant(Value::Keyword(key));
|
||||||
self.visit(value);
|
self.visit(value);
|
||||||
|
|
|
@ -46,15 +46,15 @@ mod op;
|
||||||
mod compiler;
|
mod compiler;
|
||||||
use crate::compiler::Compiler;
|
use crate::compiler::Compiler;
|
||||||
|
|
||||||
mod value;
|
pub mod value;
|
||||||
use value::Value;
|
use value::{Value, Key};
|
||||||
|
|
||||||
mod vm;
|
mod vm;
|
||||||
use vm::Creature;
|
use vm::Creature;
|
||||||
|
|
||||||
const PRELUDE: &str = include_str!("../assets/test_prelude.ld");
|
const PRELUDE: &str = include_str!("../assets/test_prelude.ld");
|
||||||
|
|
||||||
fn prelude() -> HashMap<&'static str, Value> {
|
fn prelude() -> HashMap<Key, Value> {
|
||||||
let tokens = lexer().parse(PRELUDE).into_output_errors().0.unwrap();
|
let tokens = lexer().parse(PRELUDE).into_output_errors().0.unwrap();
|
||||||
let (parsed, parse_errors) = parser()
|
let (parsed, parse_errors) = parser()
|
||||||
.parse(Stream::from_iter(tokens).map((0..PRELUDE.len()).into(), |(t, s)| (t, s)))
|
.parse(Stream::from_iter(tokens).map((0..PRELUDE.len()).into(), |(t, s)| (t, s)))
|
||||||
|
@ -71,7 +71,7 @@ fn prelude() -> HashMap<&'static str, Value> {
|
||||||
|
|
||||||
let base = base::make_base();
|
let base = base::make_base();
|
||||||
let mut base_env = imbl::HashMap::new();
|
let mut base_env = imbl::HashMap::new();
|
||||||
base_env.insert("base", base.clone());
|
base_env.insert(Key::Keyword("base"), base.clone());
|
||||||
|
|
||||||
let mut validator = Validator::new(ast, span, "prelude", PRELUDE, base_env);
|
let mut validator = Validator::new(ast, span, "prelude", PRELUDE, base_env);
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
use rudus::ludus;
|
use rudus::value::Value;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::fs;
|
use struct_scalpel::print_dissection_info;
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
env::set_var("RUST_BACKTRACE", "1");
|
env::set_var("RUST_BACKTRACE", "1");
|
||||||
let src = fs::read_to_string("sandbox.ld").unwrap();
|
print_dissection_info::<Value>();
|
||||||
let json = ludus(src);
|
|
||||||
// println!("{json}");
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,7 +79,7 @@ fn parse_string(s: &'static str, span: SimpleSpan) -> Result<Vec<Spanned<StringP
|
||||||
'}' => {
|
'}' => {
|
||||||
if is_word {
|
if is_word {
|
||||||
parts.push((
|
parts.push((
|
||||||
StringPart::Word(current_part.clone()),
|
StringPart::Word(current_part.leak()),
|
||||||
SimpleSpan::new(span.context(), start..start + i),
|
SimpleSpan::new(span.context(), start..start + i),
|
||||||
));
|
));
|
||||||
current_part = String::new();
|
current_part = String::new();
|
||||||
|
@ -209,19 +209,24 @@ where
|
||||||
.delimited_by(just(Token::Punctuation("[")), just(Token::Punctuation("]")))
|
.delimited_by(just(Token::Punctuation("[")), just(Token::Punctuation("]")))
|
||||||
.map_with(|list, e| (ListPattern(list), e.span()));
|
.map_with(|list, e| (ListPattern(list), e.span()));
|
||||||
|
|
||||||
let pair_pattern = select! {Token::Keyword(k) => k}
|
let key_pair_pattern = select! {Token::Keyword(k) => k}
|
||||||
.then(pattern.clone())
|
.then(pattern.clone())
|
||||||
.map_with(|(key, patt), e| (PairPattern(key, Box::new(patt)), e.span()));
|
.map_with(|(key, patt), e| (KeyPairPattern(key, Box::new(patt)), e.span()));
|
||||||
|
|
||||||
let shorthand_pattern = select! {Token::Word(w) => w}.map_with(|w, e| {
|
let shorthand_pattern = select! {Token::Word(w) => w}.map_with(|w, e| {
|
||||||
(
|
(
|
||||||
PairPattern(w, Box::new((WordPattern(w), e.span()))),
|
KeyPairPattern(w, Box::new((WordPattern(w), e.span()))),
|
||||||
e.span(),
|
e.span(),
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
let dict_pattern = pair_pattern
|
let str_pair_pattern = select! {Token::String(s) => s}
|
||||||
|
.then(pattern.clone())
|
||||||
|
.map_with(|(key, patt), e| (StrPairPattern(key, Box::new(patt)), e.span()));
|
||||||
|
|
||||||
|
let dict_pattern = key_pair_pattern
|
||||||
.or(shorthand_pattern)
|
.or(shorthand_pattern)
|
||||||
|
.or(str_pair_pattern)
|
||||||
.or(splattern.clone())
|
.or(splattern.clone())
|
||||||
.separated_by(separators.clone())
|
.separated_by(separators.clone())
|
||||||
.allow_leading()
|
.allow_leading()
|
||||||
|
@ -334,15 +339,20 @@ where
|
||||||
.delimited_by(just(Token::Punctuation("[")), just(Token::Punctuation("]")))
|
.delimited_by(just(Token::Punctuation("[")), just(Token::Punctuation("]")))
|
||||||
.map_with(|list, e| (List(list), e.span()));
|
.map_with(|list, e| (List(list), e.span()));
|
||||||
|
|
||||||
let pair = select! {Token::Keyword(k) => k}
|
let key_pair = select! {Token::Keyword(k) => k}
|
||||||
.then(simple.clone())
|
.then(simple.clone())
|
||||||
.map_with(|(key, value), e| (Pair(key, Box::new(value)), e.span()));
|
.map_with(|(key, value), e| (KeywordPair(key, Box::new(value)), e.span()));
|
||||||
|
|
||||||
let shorthand = select! {Token::Word(w) => w}
|
let shorthand = select! {Token::Word(w) => w}
|
||||||
.map_with(|w, e| (Pair(w, Box::new((Word(w), e.span()))), e.span()));
|
.map_with(|w, e| (KeywordPair(w, Box::new((Word(w), e.span()))), e.span()));
|
||||||
|
|
||||||
let dict = pair
|
let str_pair = select! {Token::String(s) => s}
|
||||||
|
.then(simple.clone())
|
||||||
|
.map_with(|(key, value), e| (StringPair(key, Box::new(value)), e.span()));
|
||||||
|
|
||||||
|
let dict = key_pair
|
||||||
.or(shorthand)
|
.or(shorthand)
|
||||||
|
.or(str_pair)
|
||||||
.or(splat.clone())
|
.or(splat.clone())
|
||||||
.separated_by(separators.clone())
|
.separated_by(separators.clone())
|
||||||
.allow_leading()
|
.allow_leading()
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
use crate::ast::{Ast, StringPart};
|
use crate::ast::{Ast, StringPart};
|
||||||
use crate::spans::{Span, Spanned};
|
use crate::spans::{Span, Spanned};
|
||||||
use crate::value::Value;
|
use crate::value::{Key, Value};
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
@ -61,7 +61,7 @@ fn match_arities(arities: &HashSet<Arity>, num_args: u8) -> bool {
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct Validator<'a> {
|
pub struct Validator<'a> {
|
||||||
pub locals: Vec<(String, &'a Span, FnInfo)>,
|
pub locals: Vec<(String, &'a Span, FnInfo)>,
|
||||||
pub prelude: imbl::HashMap<&'static str, Value>,
|
pub prelude: imbl::HashMap<Key, Value>,
|
||||||
pub input: &'static str,
|
pub input: &'static str,
|
||||||
pub src: &'static str,
|
pub src: &'static str,
|
||||||
pub ast: &'a Ast,
|
pub ast: &'a Ast,
|
||||||
|
@ -77,7 +77,7 @@ impl<'a> Validator<'a> {
|
||||||
span: &'a Span,
|
span: &'a Span,
|
||||||
input: &'static str,
|
input: &'static str,
|
||||||
src: &'static str,
|
src: &'static str,
|
||||||
prelude: imbl::HashMap<&'static str, Value>,
|
prelude: imbl::HashMap<Key, Value>,
|
||||||
) -> Validator<'a> {
|
) -> Validator<'a> {
|
||||||
Validator {
|
Validator {
|
||||||
input,
|
input,
|
||||||
|
@ -113,9 +113,12 @@ impl<'a> Validator<'a> {
|
||||||
self.locals[i] = new_binding;
|
self.locals[i] = new_binding;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolved(&self, name: &str) -> bool {
|
fn resolved(&self, name: &'static str) -> bool {
|
||||||
self.locals.iter().any(|(bound, ..)| name == bound.as_str())
|
self.locals.iter().any(|(bound, ..)| name == bound.as_str())
|
||||||
|| self.prelude.iter().any(|(bound, _)| name == *bound)
|
|| self
|
||||||
|
.prelude
|
||||||
|
.iter()
|
||||||
|
.any(|(bound, _)| Key::Keyword(name) == *bound)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bound(&self, name: &str) -> Option<&(String, &Span, FnInfo)> {
|
fn bound(&self, name: &str) -> Option<&(String, &Span, FnInfo)> {
|
||||||
|
@ -172,7 +175,7 @@ impl<'a> Validator<'a> {
|
||||||
for part in parts {
|
for part in parts {
|
||||||
if let (StringPart::Word(name), span) = part {
|
if let (StringPart::Word(name), span) = part {
|
||||||
self.span = span;
|
self.span = span;
|
||||||
if !self.resolved(name.as_str()) {
|
if !self.resolved(name) {
|
||||||
self.err(format!("unbound name `{name}`"));
|
self.err(format!("unbound name `{name}`"));
|
||||||
} else {
|
} else {
|
||||||
self.use_name(name.to_string());
|
self.use_name(name.to_string());
|
||||||
|
@ -267,7 +270,7 @@ impl<'a> Validator<'a> {
|
||||||
|
|
||||||
self.status.tail_position = tailpos;
|
self.status.tail_position = tailpos;
|
||||||
}
|
}
|
||||||
Pair(_, value) => self.visit(value.as_ref()),
|
KeywordPair(_, value) | StringPair(_, value) => self.visit(value.as_ref()),
|
||||||
Dict(dict) => {
|
Dict(dict) => {
|
||||||
if dict.is_empty() {
|
if dict.is_empty() {
|
||||||
return;
|
return;
|
||||||
|
@ -592,7 +595,7 @@ impl<'a> Validator<'a> {
|
||||||
self.visit(last);
|
self.visit(last);
|
||||||
self.status.last_term = false;
|
self.status.last_term = false;
|
||||||
}
|
}
|
||||||
PairPattern(_, patt) => self.visit(patt.as_ref()),
|
KeyPairPattern(_, patt) | StrPairPattern(_, patt) => self.visit(patt.as_ref()),
|
||||||
// terminals can never be invalid
|
// terminals can never be invalid
|
||||||
Nil | Boolean(_) | Number(_) | Keyword(_) | String(_) | And | Or | Method(..) => (),
|
Nil | Boolean(_) | Number(_) | Keyword(_) | String(_) | And | Or | Method(..) => (),
|
||||||
// terminal patterns can never be invalid
|
// terminal patterns can never be invalid
|
||||||
|
|
|
@ -3,6 +3,7 @@ use crate::chunk::Chunk;
|
||||||
use imbl::{HashMap, Vector};
|
use imbl::{HashMap, Vector};
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use struct_scalpel::Dissectible;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum LFn {
|
pub enum LFn {
|
||||||
|
@ -141,14 +142,14 @@ impl Key {
|
||||||
pub fn from_value(value: Value) -> Key {
|
pub fn from_value(value: Value) -> Key {
|
||||||
match value {
|
match value {
|
||||||
Value::Keyword(s) => Key::Keyword(s),
|
Value::Keyword(s) => Key::Keyword(s),
|
||||||
Value::Interned(s) => Key::Keyword(s),
|
Value::Interned(s) => Key::Interned(s),
|
||||||
Value::String(s) => Key::String(s.clone()),
|
Value::String(s) => Key::String(s.clone()),
|
||||||
_ => unreachable!("dict keys must be keywords or strings"),
|
_ => unreachable!("dict keys must be keywords or strings"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug, Dissectible)]
|
||||||
pub enum Value {
|
pub enum Value {
|
||||||
Nothing,
|
Nothing,
|
||||||
Nil,
|
Nil,
|
||||||
|
@ -163,7 +164,7 @@ pub enum Value {
|
||||||
Dict(Box<HashMap<Key, Value>>),
|
Dict(Box<HashMap<Key, Value>>),
|
||||||
Box(Rc<RefCell<Value>>),
|
Box(Rc<RefCell<Value>>),
|
||||||
Fn(Rc<LFn>),
|
Fn(Rc<LFn>),
|
||||||
BaseFn(BaseFn),
|
BaseFn(Box<BaseFn>),
|
||||||
Partial(Rc<Partial>),
|
Partial(Rc<Partial>),
|
||||||
Process,
|
Process,
|
||||||
}
|
}
|
||||||
|
@ -233,7 +234,7 @@ impl std::fmt::Display for Value {
|
||||||
Box(value) => write!(f, "box {{ {} }}", value.as_ref().borrow()),
|
Box(value) => write!(f, "box {{ {} }}", value.as_ref().borrow()),
|
||||||
Fn(lfn) => write!(f, "fn {}", lfn.name()),
|
Fn(lfn) => write!(f, "fn {}", lfn.name()),
|
||||||
BaseFn(inner) => {
|
BaseFn(inner) => {
|
||||||
let name = match inner {
|
let name = match **inner {
|
||||||
crate::base::BaseFn::Nullary(name, _)
|
crate::base::BaseFn::Nullary(name, _)
|
||||||
| crate::base::BaseFn::Unary(name, _)
|
| crate::base::BaseFn::Unary(name, _)
|
||||||
| crate::base::BaseFn::Binary(name, _)
|
| crate::base::BaseFn::Binary(name, _)
|
||||||
|
|
45
src/vm.rs
45
src/vm.rs
|
@ -3,7 +3,7 @@ use crate::base::BaseFn;
|
||||||
use crate::chunk::Chunk;
|
use crate::chunk::Chunk;
|
||||||
use crate::op::Op;
|
use crate::op::Op;
|
||||||
use crate::spans::Spanned;
|
use crate::spans::Spanned;
|
||||||
use crate::value::{LFn, Value};
|
use crate::value::{Key, LFn, Value};
|
||||||
use crate::world::Zoo;
|
use crate::world::Zoo;
|
||||||
use imbl::{HashMap, Vector};
|
use imbl::{HashMap, Vector};
|
||||||
use num_traits::FromPrimitive;
|
use num_traits::FromPrimitive;
|
||||||
|
@ -477,7 +477,7 @@ impl Creature {
|
||||||
let Value::Keyword(name) = key else {
|
let Value::Keyword(name) = key else {
|
||||||
unreachable!("internal Ludus error: expected key for global resolution")
|
unreachable!("internal Ludus error: expected key for global resolution")
|
||||||
};
|
};
|
||||||
let value = self.chunk().env.get(name).unwrap();
|
let value = self.chunk().env.get(&Key::Keyword(name)).unwrap();
|
||||||
self.push(value.clone());
|
self.push(value.clone());
|
||||||
}
|
}
|
||||||
Store => {
|
Store => {
|
||||||
|
@ -700,9 +700,7 @@ impl Creature {
|
||||||
}
|
}
|
||||||
AppendDict => {
|
AppendDict => {
|
||||||
let value = self.pop();
|
let value = self.pop();
|
||||||
let Value::Keyword(key) = self.pop() else {
|
let key = Key::from_value(self.pop());
|
||||||
unreachable!()
|
|
||||||
};
|
|
||||||
let Value::Dict(mut dict) = self.pop() else {
|
let Value::Dict(mut dict) = self.pop() else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
|
@ -731,9 +729,7 @@ impl Creature {
|
||||||
unreachable!("expected dict, got {value}")
|
unreachable!("expected dict, got {value}")
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let Value::Keyword(key) = self.pop() else {
|
let key = Key::from_value(self.pop());
|
||||||
unreachable!("expected keyword, got something else")
|
|
||||||
};
|
|
||||||
let value = dict.get(&key).unwrap_or(&Value::Nil);
|
let value = dict.get(&key).unwrap_or(&Value::Nil);
|
||||||
self.push(value.clone());
|
self.push(value.clone());
|
||||||
}
|
}
|
||||||
|
@ -756,13 +752,11 @@ impl Creature {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DropDictEntry => {
|
DropDictEntry => {
|
||||||
let Value::Keyword(key_to_drop) = self.pop() else {
|
let key_to_drop = Key::from_value(self.pop());
|
||||||
unreachable!()
|
|
||||||
};
|
|
||||||
let Value::Dict(mut dict) = self.pop() else {
|
let Value::Dict(mut dict) = self.pop() else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
dict.remove(key_to_drop);
|
dict.remove(&key_to_drop);
|
||||||
self.push(Value::Dict(dict));
|
self.push(Value::Dict(dict));
|
||||||
}
|
}
|
||||||
PushBox => {
|
PushBox => {
|
||||||
|
@ -770,13 +764,10 @@ impl Creature {
|
||||||
self.push(Value::Box(Rc::new(RefCell::new(val))));
|
self.push(Value::Box(Rc::new(RefCell::new(val))));
|
||||||
}
|
}
|
||||||
GetKey => {
|
GetKey => {
|
||||||
let key = self.pop();
|
let key = Key::from_value(self.pop());
|
||||||
let Value::Keyword(idx) = key else {
|
|
||||||
unreachable!()
|
|
||||||
};
|
|
||||||
let dict = self.pop();
|
let dict = self.pop();
|
||||||
let value = match dict {
|
let value = match dict {
|
||||||
Value::Dict(d) => d.as_ref().get(&idx).unwrap_or(&Value::Nil).clone(),
|
Value::Dict(d) => d.get(&key).unwrap_or(&Value::Nil).clone(),
|
||||||
_ => Value::Nil,
|
_ => Value::Nil,
|
||||||
};
|
};
|
||||||
self.push(value);
|
self.push(value);
|
||||||
|
@ -899,13 +890,17 @@ impl Creature {
|
||||||
}
|
}
|
||||||
Get => {
|
Get => {
|
||||||
let key = self.pop();
|
let key = self.pop();
|
||||||
let dict = self.pop();
|
if !matches!(
|
||||||
let value = match (key, dict) {
|
key,
|
||||||
(Value::Keyword(k), Value::Dict(d)) => {
|
Value::Keyword(_) | Value::String(_) | Value::Interned(_)
|
||||||
d.as_ref().get(&k).unwrap_or(&Value::Nil).clone()
|
) {
|
||||||
|
return self.panic("keys must be keywords");
|
||||||
}
|
}
|
||||||
(Value::Keyword(_), _) => Value::Nil,
|
let key = Key::from_value(key);
|
||||||
_ => return self.panic("keys must be keywords"),
|
let dict = self.pop();
|
||||||
|
let value = match dict {
|
||||||
|
Value::Dict(d) => d.get(&key).unwrap_or(&Value::Nil).clone(),
|
||||||
|
_ => Value::Nil.clone(),
|
||||||
};
|
};
|
||||||
self.push(value);
|
self.push(value);
|
||||||
}
|
}
|
||||||
|
@ -1042,7 +1037,7 @@ impl Creature {
|
||||||
self.ip = 0;
|
self.ip = 0;
|
||||||
}
|
}
|
||||||
Value::BaseFn(base_fn) => {
|
Value::BaseFn(base_fn) => {
|
||||||
let value = match (arity, base_fn) {
|
let value = match (arity, *base_fn) {
|
||||||
(0, BaseFn::Nullary(_, f)) => f(),
|
(0, BaseFn::Nullary(_, f)) => f(),
|
||||||
(1, BaseFn::Unary(_, f)) => f(&self.pop()),
|
(1, BaseFn::Unary(_, f)) => f(&self.pop()),
|
||||||
(2, BaseFn::Binary(_, f)) => {
|
(2, BaseFn::Binary(_, f)) => {
|
||||||
|
@ -1149,7 +1144,7 @@ impl Creature {
|
||||||
self.ip = 0;
|
self.ip = 0;
|
||||||
}
|
}
|
||||||
Value::BaseFn(base_fn) => {
|
Value::BaseFn(base_fn) => {
|
||||||
let value = match (arity, base_fn) {
|
let value = match (arity, *base_fn) {
|
||||||
(0, BaseFn::Nullary(_, f)) => f(),
|
(0, BaseFn::Nullary(_, f)) => f(),
|
||||||
(1, BaseFn::Unary(_, f)) => f(&self.pop()),
|
(1, BaseFn::Unary(_, f)) => f(&self.pop()),
|
||||||
(2, BaseFn::Binary(_, f)) => {
|
(2, BaseFn::Binary(_, f)) => {
|
||||||
|
|
16
src/world.rs
16
src/world.rs
|
@ -1,5 +1,5 @@
|
||||||
use crate::chunk::Chunk;
|
use crate::chunk::Chunk;
|
||||||
use crate::value::Value;
|
use crate::value::{Value, Key};
|
||||||
use crate::vm::{Creature, Panic};
|
use crate::vm::{Creature, Panic};
|
||||||
use crate::io::{MsgOut, MsgIn, do_io};
|
use crate::io::{MsgOut, MsgIn, do_io};
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
@ -260,13 +260,13 @@ pub struct Buffers {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Buffers {
|
impl Buffers {
|
||||||
pub fn new (prelude: imbl::HashMap<&'static str, Value>) -> Buffers {
|
pub fn new (prelude: imbl::HashMap<Key, Value>) -> Buffers {
|
||||||
Buffers {
|
Buffers {
|
||||||
console: prelude.get("console").unwrap().clone(),
|
console: prelude.get(&Key::Keyword("console")).unwrap().clone(),
|
||||||
commands: prelude.get("turtle_commands").unwrap().clone(),
|
commands: prelude.get(&Key::Keyword("turtle_commands")).unwrap().clone(),
|
||||||
fetch_out: prelude.get("fetch_outbox").unwrap().clone(),
|
fetch_out: prelude.get(&Key::Keyword("fetch_outbox")).unwrap().clone(),
|
||||||
fetch_in: prelude.get("fetch_inbox").unwrap().clone(),
|
fetch_in: prelude.get(&Key::Keyword("fetch_inbox")).unwrap().clone(),
|
||||||
input: prelude.get("input").unwrap().clone(),
|
input: prelude.get(&Key::Keyword("input")).unwrap().clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -304,7 +304,7 @@ pub struct World {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl World {
|
impl World {
|
||||||
pub fn new(chunk: Chunk, prelude: imbl::HashMap<&'static str, Value>, debug: bool) -> World {
|
pub fn new(chunk: Chunk, prelude: imbl::HashMap<Key, Value>, debug: bool) -> World {
|
||||||
let zoo = Rc::new(RefCell::new(Zoo::new()));
|
let zoo = Rc::new(RefCell::new(Zoo::new()));
|
||||||
let main = Creature::new(chunk, zoo.clone(), debug);
|
let main = Creature::new(chunk, zoo.clone(), debug);
|
||||||
let id = zoo.borrow_mut().put(main);
|
let id = zoo.borrow_mut().put(main);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user