Skip to content

Commit

Permalink
object implemented
Browse files Browse the repository at this point in the history
  • Loading branch information
sty00A4 committed Jan 2, 2023
1 parent f7a1337 commit f8cc679
Show file tree
Hide file tree
Showing 9 changed files with 262 additions and 140 deletions.
92 changes: 92 additions & 0 deletions samples/math_parser.nd
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
; --- LEXER ---
(def-global @tokenize $(in str) #{
(mut @tokens (vec any []))
(mut @idx 0)
(while #(< idx (len in)) #{
; skip white space
(while #(contains [' ' '\t' '\r' '\n'] (in idx)) #{
(inc! @idx)
(if (>= idx (len in)) #(break))
})
(if (>= idx (len in)) #(break))
; number
(if (digit? (in idx)) #{
(mut @num "")
(while #(digit? (in idx)) #{
(str-push @num (in idx))
(inc! @idx)
(if (>= idx (len in)) #(break))
})
(push @tokens (int num))
; symbol
} #(if (contains ['+' '-' '*' '/' '(' ')'] (in idx)) #{
(push @tokens (in idx))
(inc! @idx)
} #(inc! @idx)))
})
(return tokens)
})
; --- PARSER ---
(def-global-inline @atom $(:tokens key :idx key) #{
(let @token ((get :tokens) (get :idx)))
(inc! :idx)
(if (= (type token) int) #(return ${ typ "int" value token }))
(if (= token '(') #{
(if (not (exist? (index :tokens (get :idx)))) #(error! "unexpected end"))
(let @node (expr :tokens :idx))
(if (!= token ')') #(error! "expected ')'"))
(inc! :idx)
(return node)
})
(error! (concat "unexpected '" (str ((get :tokens) (get :idx))) "'"))
})
(def-global-inline @factor $(:tokens key :idx key) #{
(if (contains ['-' '+'] ((get :tokens) (get :idx))) #{
(let @op ((get :tokens) (get :idx)))
(inc! :idx)(if (not (exist? (index :tokens (get :idx)))) #(error! "unexpected end"))
(return ${ typ "unary" op op node (factor :tokens :idx) })
})
(return (atom :tokens :idx))
})
(def-global-inline @term $(:tokens key :idx key) #{
(mut @left (factor :tokens :idx))
(if (not (exist? (index :tokens (get :idx)))) #(return left))
(while #(contains ['*' '/'] ((get :tokens) (get :idx))) #{
(let @op ((get :tokens) (get :idx)))
(inc! :idx)(if (not (exist? (index :tokens (get :idx)))) #(error! "unexpected end"))
(let @right (factor :tokens :idx))
(set @left ${ typ "binary" left left op op right right })
(if (not (exist? (index :tokens (get :idx)))) #(break))
})
(return left)
})
(def-global-inline @arith $(:tokens key :idx key) #{
(mut @left (term :tokens :idx))
(if (not (exist? (index :tokens (get :idx)))) #(return left))
(while #(contains ['+' '-'] ((get :tokens) (get :idx))) #{
(let @op ((get :tokens) (get :idx)))
(inc! :idx)(if (not (exist? (index :tokens (get :idx)))) #(error! "unexpected end"))
(let @right (term :tokens :idx))
(set @left ${ typ "binary" left left op op right right })
(if (not (exist? (index :tokens (get :idx)))) #(break))
})
(return left)
})
(def-global-inline @expr $(:tokens key :idx key) #(arith :tokens :idx))
(def-global @parse $(tokens (vec any)) #{
(mut @idx 0)
(return (expr @tokens @idx))
})
(def-global @ast-to-str $(ast obj)
#(if (= (ast @typ) "binary")
#(concat "(" (ast-to-str (ast @left)) " " (ast @op) " " (ast-to-str (ast @right)) ")")
#(if (= (ast @typ) "unary")
#(concat "(" (ast @op) (ast-to-str (ast @node)) ")")
#(if (= (ast @typ) "int")
#(str (ast @value))
#(error! ("unsupported node type: " (? (exist? (path @ast @typ)) (str (ast @typ)) "?")))
)))
)
; --- TESTS ---
(print (ast-to-str (parse (tokenize "1 + 2 * 3"))))
(print (ast-to-str (parse (tokenize "(1 + 2) * 3"))))
28 changes: 0 additions & 28 deletions samples/tokenizer.nd

This file was deleted.

8 changes: 4 additions & 4 deletions src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ use crate::*;

#[derive(Debug, Clone)]
pub struct Scope {
vars: HashMap<String, (Value, bool, Position)>,
funcs: HashMap<String, Vec<(Function, Position)>>,
native_funcs: HashMap<String, Vec<(NativFunction, Position)>>,
subs: HashMap<String, Scope>
pub vars: HashMap<String, (Value, bool, Position)>,
pub funcs: HashMap<String, Vec<(Function, Position)>>,
pub native_funcs: HashMap<String, Vec<(NativFunction, Position)>>,
pub subs: HashMap<String, Scope>
}
impl Scope {
pub fn new() -> Self {
Expand Down
9 changes: 7 additions & 2 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ pub fn patterns_display(patterns: &Vec<Vec<(Type, bool)>>) -> String {
}
#[derive(Debug, Clone)]
pub enum Error {
Error(String),
TargetFileNotFound(String),
UnexpectedEnd, UnexpectedSymbol(char), ExpectedSymbol(char, char), ExpectedWord,
UnexpectedEnd, UnexpectedSymbol(char), ExpectedSymbol(char, char), ExpectedSymbols(Vec<char>, char), ExpectedWord,
ParseFloat(String), ParseInt(String), ParseIntOverflow(String), ParseIntNegOverflow(String),
ParseChar(String), ParseBool(String), ParseString(String),
UnclosedChar, UnclosedString,
Expand All @@ -30,15 +31,18 @@ pub enum Error {
Expected, ExpectedArg, ExpectedType(Type, Type), ExpectedTypes(Vec<Type>, Type),
FunctionPatternNotFound(String, Vec<Type>, Vec<Vec<(Type, bool)>>), ValuePatternNotFound(Type, Vec<Type>),
InvalidHeadValue(Value), InvalidHeadCastType(Type), InvalidCastBetween(Type, Type),
IndexOutOfRange(usize, usize), IllegalNegativeIndex(i64)
IndexOutOfRange(usize, usize), IllegalNegativeIndex(i64),
NotDefinedKey(String)
}
impl Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Error(msg) => write!(f, "ERROR: {msg}"),
Self::TargetFileNotFound(path) => write!(f, "ERROR: {path:?} couldn't be found in the current directory"),
Self::UnexpectedEnd => write!(f, "ERROR: unexpected end of input"),
Self::UnexpectedSymbol(s) => write!(f, "ERROR: unexpected {s:?}"),
Self::ExpectedSymbol(expected, got) => write!(f, "ERROR: expected {expected:?}, got {got:?}"),
Self::ExpectedSymbols(expected, got) => write!(f, "ERROR: expected {:?}, got {got:?}", expected.iter().map(|x| x.to_string()).collect::<Vec<String>>().join("|")),
Self::ExpectedWord => write!(f, "ERROR: expected the beginning of a word here"),
Self::ParseFloat(n) => write!(f, "ERROR: {n:?} couldn't be parsed as a float"),
Self::ParseInt(n) => write!(f, "ERROR: {n:?} couldn't be parsed as an int"),
Expand Down Expand Up @@ -70,6 +74,7 @@ impl Display for Error {
Self::InvalidCastBetween(t1, t2) => write!(f, "ERROR: invalid cast from {t2} to {t1}"),
Self::IndexOutOfRange(idx, size) => write!(f, "ERROR: index {idx} out of range of size {size}"),
Self::IllegalNegativeIndex(idx) => write!(f, "ERROR: illegal negative index {idx}"),
Self::NotDefinedKey(key) => write!(f, "ERROR: {key:?} doesn't exist in object"),
}
}
}
Expand Down
36 changes: 35 additions & 1 deletion src/interpret.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ pub fn interpret(node: &Node, context: &mut Context) -> Result<(Option<Value>, R
if let Value::Type(typ) = typ {
params.push((param.clone(), typ, *more));
} else {
context.trace_push(pos);
context.trace_push(type_node.pos());
return Err(Error::ExpectedType(Type::Type, typ.typ()))
}
} else {
Expand All @@ -62,6 +62,19 @@ pub fn interpret(node: &Node, context: &mut Context) -> Result<(Option<Value>, R
}
Ok((Some(Value::Params(params)), Return::None))
}
Node::Object { entries, pos } => {
let mut obj_scope = Scope::new();
for (key, value_node) in entries.iter() {
let (value, _) = interpret(value_node, context)?;
if let Some(value) = value {
obj_scope.create_var(key.clone(), value, true, value_node.pos().clone(), true)?;
} else {
context.trace_push(value_node.pos());
return Err(Error::Expected)
}
}
Ok((Some(Value::Object(obj_scope)), Return::None))
}
Node::Body { nodes, pos:_ } => {
context.push();
for node in nodes.iter() {
Expand Down Expand Up @@ -183,6 +196,27 @@ pub fn interpret(node: &Node, context: &mut Context) -> Result<(Option<Value>, R
context.trace_push(&poses[0]);
Err(Error::ValuePatternNotFound(Type::Vector(Some(Box::new(Type::Any))), types))
}
Value::Object(obj_scope) => if values.len() == 1 {
context.pop();
match &values[0] {
Value::Key(key) => {
match obj_scope.get_var(key) {
Some(value) => Ok((Some(value.clone()), Return::None)),
None => {
context.trace_push(&poses[0]);
Err(Error::NotDefinedKey(key.clone()))
}
}
}
_ => {
context.trace_push(&poses[0]);
Err(Error::ExpectedTypes(vec![Type::Key], types[0].clone()))
}
}
} else {
context.trace_push(&poses[0]);
Err(Error::ValuePatternNotFound(Type::Vector(Some(Box::new(Type::Any))), types))
}
Value::String(string) => if values.len() == 1 {
context.pop();
if let Value::Int(idx) = &values[0] {
Expand Down
13 changes: 12 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ use std::fmt::{Debug, Display};
use core::num::IntErrorKind;
use std::cmp::{min, max};
use std::io::Write;
use std::thread;

const STACK_SIZE: usize = 4 * 1024 * 1024;

pub fn run(path: &String, text: String) -> Result<(Option<Value>, Return), Error> {
let mut context = std_context()?;
Expand All @@ -39,7 +42,7 @@ pub fn run_file_context(path: &String, context: &mut Context) -> Result<(Option<
}
}

fn main() {
pub fn nody() {
let args: Vec<String> = std::env::args().collect();
let mut args = args.iter();
args.next();
Expand All @@ -58,6 +61,14 @@ fn main() {
}
}

fn main() {
let program = thread::Builder::new()
.stack_size(STACK_SIZE)
.spawn(nody)
.unwrap();
program.join().unwrap();
}

#[cfg(test)]
mod test {
use super::*;
Expand Down
22 changes: 20 additions & 2 deletions src/nody_std.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,13 +131,19 @@ fn _exist(context: &mut Context) -> Result<(Option<Value>, Return), Error> {
fn _exist_path(context: &mut Context) -> Result<(Option<Value>, Return), Error> {
let path = context.get_var(&":path".to_string()).unwrap().clone();
if let Value::Path(path) = path {
Ok((Some(Value::Bool(path.get(context)?.is_some())), Return::None))
Ok((Some(Value::Bool(match path.get(context) {
Ok(value) => value.is_some(),
Err(_) => false
})), Return::None))
} else { panic!("type checking doesn't work") }
}
fn _exist_index(context: &mut Context) -> Result<(Option<Value>, Return), Error> {
let index = context.get_var(&":index".to_string()).unwrap().clone();
if let Value::Index(index) = index {
Ok((Some(Value::Bool(index.get(context)?.is_some())), Return::None))
Ok((Some(Value::Bool(match index.get(context) {
Ok(value) => value.is_some(),
Err(_) => false
})), Return::None))
} else { panic!("type checking doesn't work") }
}
fn _is_mut(context: &mut Context) -> Result<(Option<Value>, Return), Error> {
Expand Down Expand Up @@ -1069,6 +1075,12 @@ fn _input(context: &mut Context) -> Result<(Option<Value>, Return), Error> {
Ok((Some(Value::String(input)), Return::None))
} else { panic!("type checking doesn't work") }
}
fn _error(context: &mut Context) -> Result<(Option<Value>, Return), Error> {
let msg = context.get_var(&"msg".to_string()).unwrap();
if let Value::String(msg) = msg {
Err(Error::Error(msg.clone()))
} else { panic!("type checking doesn't work") }
}

pub fn std_context() -> Result<Context, Error> {
let mut context = Context::new();
Expand Down Expand Up @@ -1734,6 +1746,12 @@ pub fn std_context() -> Result<Context, Error> {
body: _input,
inline: false
}, pos.clone())?;
context.create_native_fn(String::from("error!"), NativFunction {
params: vec![("msg".to_string(), Type::String, false)],
return_type: None,
body: _error,
inline: false
}, pos.clone())?;
let std_path = String::from("nody_std/std.nd");
let _ = run_file_context(&std_path, &mut context)?;
context.scopes = vec![Scope::new()];
Expand Down
Loading

0 comments on commit f8cc679

Please sign in to comment.