things and stuff
This commit is contained in:
parent
333f5c9518
commit
80eb81c6a8
12
Cargo.toml
12
Cargo.toml
|
@ -6,18 +6,18 @@ edition = "2021"
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[dependencies]
|
||||
ariadne = { git = "https://github.com/zesterer/ariadne" }
|
||||
chumsky = { git = "https://github.com/zesterer/chumsky", features = ["label"] }
|
||||
imbl = "3.0.0"
|
||||
struct_scalpel = "0.1.1"
|
||||
# struct_scalpel = "0.1.1"
|
||||
ran = "2.0.1"
|
||||
rust-embed = "8.5.0"
|
||||
boxing = "0.1.2"
|
||||
ordered-float = "4.5.0"
|
||||
index_vec = "0.1.4"
|
||||
# rust-embed = "8.5.0"
|
||||
# boxing = "0.1.2"
|
||||
# ordered-float = "4.5.0"
|
||||
# index_vec = "0.1.4"
|
||||
num-derive = "0.4.2"
|
||||
num-traits = "0.2.19"
|
||||
regex = "1.11.1"
|
||||
|
|
19
package.json
Normal file
19
package.json
Normal file
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"name": "@ludus/rudus",
|
||||
"version": "0.1.1",
|
||||
"description": "A Rust-based Ludus bytecode interpreter.",
|
||||
"type": "common",
|
||||
"main": "pkg/ludus.js",
|
||||
"directories": {},
|
||||
"keywords": [],
|
||||
"author": "Scott Richmond",
|
||||
"license": "GPL-3.0",
|
||||
"files": [
|
||||
"pkg/rudus.js",
|
||||
"pkg/ludus.js",
|
||||
"pkg/rudus_bg.wasm",
|
||||
"pkg/rudus_bg.wasm.d.ts",
|
||||
"pkg/rudus.d.ts"
|
||||
],
|
||||
"devDependencies": {}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
print! (:foo, :bar, :baz)
|
||||
print! ("I wrote something")
|
||||
let false = true
|
||||
print! (1, 2, 3)
|
||||
repeat 1 {
|
||||
fd! (100)
|
||||
rt! (0.25)
|
||||
}
|
||||
|
|
23
src/lib.rs
23
src/lib.rs
|
@ -38,7 +38,7 @@ use vm::Vm;
|
|||
|
||||
const PRELUDE: &str = include_str!("../assets/test_prelude.ld");
|
||||
|
||||
pub fn prelude() -> HashMap<&'static str, Value> {
|
||||
fn prelude() -> HashMap<&'static str, Value> {
|
||||
let tokens = lexer().parse(PRELUDE).into_output_errors().0.unwrap();
|
||||
let (parsed, parse_errors) = parser()
|
||||
.parse(Stream::from_iter(tokens).map((0..PRELUDE.len()).into(), |(t, s)| (t, s)))
|
||||
|
@ -91,7 +91,7 @@ pub fn prelude() -> HashMap<&'static str, Value> {
|
|||
|
||||
#[wasm_bindgen]
|
||||
pub fn run(src: String) -> String {
|
||||
let src = src.leak();
|
||||
let src = src.to_string().leak();
|
||||
let (tokens, lex_errs) = lexer().parse(src).into_output_errors();
|
||||
if !lex_errs.is_empty() {
|
||||
return format!("{:?}", lex_errs);
|
||||
|
@ -163,7 +163,9 @@ pub fn run(src: String) -> String {
|
|||
let Value::Box(commands) = turtle_commands else {
|
||||
unreachable!()
|
||||
};
|
||||
let commands = commands.borrow().to_json().unwrap();
|
||||
let commands = commands.borrow();
|
||||
dbg!(&commands);
|
||||
let commands = commands.to_json().unwrap();
|
||||
|
||||
let output = match result {
|
||||
Ok(val) => val.show(),
|
||||
|
@ -178,22 +180,11 @@ pub fn run(src: String) -> String {
|
|||
|
||||
// TODO: use serde_json to make this more robust?
|
||||
format!(
|
||||
"{{\"result\": \"{output}\",
|
||||
\"io\": {{
|
||||
\"stdout\": {{
|
||||
\"proto\": [\"text-stream\", \"0.1.0\"],
|
||||
\"data\": \"{console}\"
|
||||
}},
|
||||
\"turtle\": {{
|
||||
\"proto\": [\"turtle-graphics\", \"0.1.0\"],
|
||||
\"data\": {commands}
|
||||
}}
|
||||
}}
|
||||
}}"
|
||||
"{{\"result\":\"{output}\",\"io\":{{\"stdout\":{{\"proto\":[\"text-stream\",\"0.1.0\"],\"data\":\"{console}\"}},\"turtle\":{{\"proto\":[\"turtle-graphics\",\"0.1.0\"],\"data\":{commands}}}}}}}"
|
||||
)
|
||||
}
|
||||
|
||||
pub fn ld_fmt(src: &'static str) -> Result<String, String> {
|
||||
pub fn fmt(src: &'static str) -> Result<String, String> {
|
||||
let (tokens, lex_errs) = lexer().parse(src).into_output_errors();
|
||||
if !lex_errs.is_empty() {
|
||||
println!("{:?}", lex_errs);
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
use crate::lib::run;
|
||||
use rudus::run;
|
||||
use std::env;
|
||||
use std::fs;
|
||||
|
||||
mod lib;
|
||||
|
||||
pub fn main() {
|
||||
env::set_var("RUST_BACKTRACE", "1");
|
||||
let src = fs::read_to_string("sandbox.ld").unwrap();
|
||||
|
|
120
src/parser.rs
120
src/parser.rs
|
@ -1,37 +1,11 @@
|
|||
// TODO: move AST to its own module
|
||||
// TODO: remove StringMatcher cruft
|
||||
// TODO: good error messages?
|
||||
|
||||
use crate::lexer::*;
|
||||
use crate::spans::*;
|
||||
use chumsky::{input::ValueInput, prelude::*, recursive::Recursive};
|
||||
use std::fmt;
|
||||
use struct_scalpel::Dissectible;
|
||||
|
||||
// #[derive(Clone, Debug, PartialEq)]
|
||||
// pub struct WhenClause {
|
||||
// pub cond: Spanned<Ast>,
|
||||
// pub body: Spanned<Ast>,
|
||||
// }
|
||||
|
||||
// impl fmt::Display for WhenClause {
|
||||
// fn fmt(self: &WhenClause, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
// write!(f, "cond: {}, body: {}", self.cond.0, self.body.0)
|
||||
// }
|
||||
// }
|
||||
|
||||
// #[derive(Clone, Debug, PartialEq)]
|
||||
// pub struct MatchClause {
|
||||
// pub patt: Spanned<Pattern>,
|
||||
// pub guard: Option<Spanned<Ast>>,
|
||||
// pub body: Spanned<Ast>,
|
||||
// }
|
||||
|
||||
// impl fmt::Display for MatchClause {
|
||||
// fn fmt(self: &MatchClause, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
// write!(
|
||||
// f,
|
||||
// "pattern: {}, guard: {:?} body: {}",
|
||||
// self.patt.0, self.guard, self.body.0
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum StringPart {
|
||||
|
@ -51,13 +25,7 @@ impl fmt::Display for StringPart {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct LFn {
|
||||
name: &'static str,
|
||||
clauses: Vec<Spanned<Ast>>,
|
||||
doc: Option<&'static str>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Dissectible)]
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum Ast {
|
||||
// a special Error node
|
||||
// may come in handy?
|
||||
|
@ -219,14 +187,11 @@ impl Ast {
|
|||
.collect::<Vec<_>>()
|
||||
.join("\n ")
|
||||
),
|
||||
FnBody(clauses) => format!(
|
||||
"{}",
|
||||
clauses
|
||||
FnBody(clauses) => clauses
|
||||
.iter()
|
||||
.map(|(clause, _)| clause.show())
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n ")
|
||||
),
|
||||
.join("\n "),
|
||||
Fn(name, body, doc) => {
|
||||
let mut out = format!("fn {name} {{\n");
|
||||
if let Some(doc) = doc {
|
||||
|
@ -267,7 +232,7 @@ impl Ast {
|
|||
.join(", ")
|
||||
),
|
||||
MatchClause(pattern, guard, body) => {
|
||||
let mut out = format!("{}", pattern.0.show());
|
||||
let mut out = pattern.0.show();
|
||||
if let Some(guard) = guard.as_ref() {
|
||||
out = format!("{out} if {}", guard.0.show());
|
||||
}
|
||||
|
@ -523,75 +488,6 @@ impl fmt::Debug for StringMatcher {
|
|||
}
|
||||
}
|
||||
|
||||
// #[derive(Clone, Debug, PartialEq)]
|
||||
// pub enum Pattern {
|
||||
// Nil,
|
||||
// Boolean(bool),
|
||||
// Number(f64),
|
||||
// String(&'static str),
|
||||
// Interpolated(Vec<Spanned<StringPart>>, StringMatcher),
|
||||
// Keyword(&'static str),
|
||||
// Word(&'static str),
|
||||
// As(&'static str, &'static str),
|
||||
// Splattern(Box<Spanned<Self>>),
|
||||
// Placeholder,
|
||||
// Tuple(Vec<Spanned<Self>>),
|
||||
// List(Vec<Spanned<Self>>),
|
||||
// Pair(&'static str, Box<Spanned<Self>>),
|
||||
// Dict(Vec<Spanned<Self>>),
|
||||
// }
|
||||
|
||||
// impl fmt::Display for Pattern {
|
||||
// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
// match self {
|
||||
// Pattern::Nil => write!(f, "nil"),
|
||||
// Pattern::Boolean(b) => write!(f, "{}", b),
|
||||
// Pattern::Number(n) => write!(f, "{}", n),
|
||||
// Pattern::String(s) => write!(f, "{}", s),
|
||||
// Pattern::Keyword(k) => write!(f, ":{}", k),
|
||||
// Pattern::Word(w) => write!(f, "{}", w),
|
||||
// Pattern::As(w, t) => write!(f, "{} as {}", w, t),
|
||||
// Pattern::Splattern(p) => write!(f, "...{}", p.0),
|
||||
// Pattern::Placeholder => write!(f, "_"),
|
||||
// Pattern::Tuple(t) => write!(
|
||||
// f,
|
||||
// "({})",
|
||||
// t.iter()
|
||||
// .map(|x| x.0.to_string())
|
||||
// .collect::<Vec<_>>()
|
||||
// .join(", ")
|
||||
// ),
|
||||
// Pattern::List(l) => write!(
|
||||
// f,
|
||||
// "({})",
|
||||
// l.iter()
|
||||
// .map(|x| x.0.to_string())
|
||||
// .collect::<Vec<_>>()
|
||||
// .join(", ")
|
||||
// ),
|
||||
// Pattern::Dict(entries) => write!(
|
||||
// f,
|
||||
// "#{{{}}}",
|
||||
// entries
|
||||
// .iter()
|
||||
// .map(|(pair, _)| pair.to_string())
|
||||
// .collect::<Vec<_>>()
|
||||
// .join(", ")
|
||||
// ),
|
||||
// Pattern::Pair(key, value) => write!(f, ":{} {}", key, value.0),
|
||||
// Pattern::Interpolated(strprts, _) => write!(
|
||||
// f,
|
||||
// "interpolated: \"{}\"",
|
||||
// strprts
|
||||
// .iter()
|
||||
// .map(|part| part.0.to_string())
|
||||
// .collect::<Vec<_>>()
|
||||
// .join("")
|
||||
// ),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
fn is_word_char(c: char) -> bool {
|
||||
if c.is_ascii_alphanumeric() {
|
||||
return true;
|
||||
|
|
39
src/value.rs
39
src/value.rs
|
@ -258,39 +258,50 @@ impl Value {
|
|||
pub fn to_json(&self) -> Option<String> {
|
||||
use Value::*;
|
||||
match self {
|
||||
True | False | String(..) | Interned(..) => Some(self.show()),
|
||||
True | False | String(..) | Interned(..) | Number(..) => Some(self.show()),
|
||||
Keyword(str) => Some(format!("\"{str}\"")),
|
||||
List(members) => {
|
||||
let mut joined = "".to_string();
|
||||
for member in members.iter() {
|
||||
match member.to_json() {
|
||||
Some(json) => joined = format!("{joined}, {json}"),
|
||||
None => return None,
|
||||
let mut members = members.iter();
|
||||
if let Some(member) = members.next() {
|
||||
joined = member.to_json()?;
|
||||
}
|
||||
for member in members {
|
||||
let json = member.to_json()?;
|
||||
joined = format!("{joined},{json}");
|
||||
}
|
||||
Some(format!("[{joined}]"))
|
||||
}
|
||||
Tuple(members) => {
|
||||
let mut joined = "".to_string();
|
||||
for member in members.iter() {
|
||||
match member.to_json() {
|
||||
Some(json) => joined = format!("{joined}, {json}"),
|
||||
None => return None,
|
||||
let mut members = members.iter();
|
||||
if let Some(member) = members.next() {
|
||||
joined = member.to_json()?;
|
||||
}
|
||||
for member in members {
|
||||
let json = member.to_json()?;
|
||||
joined = format!("{joined},{json}");
|
||||
}
|
||||
Some(format!("[{joined}]"))
|
||||
}
|
||||
Dict(members) => {
|
||||
let mut joined = "".to_string();
|
||||
for (key, value) in members.iter() {
|
||||
match value.to_json() {
|
||||
Some(json) => joined = format!("{joined}, \"{key}\": {json}"),
|
||||
None => return None,
|
||||
let mut members = members.iter();
|
||||
if let Some((key, value)) = members.next() {
|
||||
let json = value.to_json()?;
|
||||
joined = format!("\"{key}\":{json}")
|
||||
}
|
||||
for (key, value) in members {
|
||||
let json = value.to_json()?;
|
||||
joined = format!("{joined},\"{key}\": {json}");
|
||||
}
|
||||
Some(format!("{{{joined}}}"))
|
||||
}
|
||||
_ => None,
|
||||
not_serializable => {
|
||||
println!("Cannot convert to json:");
|
||||
dbg!(not_serializable);
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user