summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock4
-rw-r--r--Cargo.toml2
-rw-r--r--a.mat5
-rw-r--r--matrix-bin/src/main.rs1
-rw-r--r--matrix-stdlib/Cargo.toml8
-rw-r--r--matrix-stdlib/src/lib.rs14
-rw-r--r--matrix/src/ast.rs12
-rw-r--r--matrix/src/chunk.rs4
-rw-r--r--matrix/src/compiler.rs45
-rw-r--r--matrix/src/gc.rs124
-rw-r--r--matrix/src/lex.rs143
-rw-r--r--matrix/src/parse.rs74
-rw-r--r--matrix/src/value.rs196
-rw-r--r--matrix/src/vm.rs46
-rw-r--r--syntax_thing63
15 files changed, 565 insertions, 176 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 30ca9f6..45a0c7e 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -224,6 +224,10 @@ dependencies = [
]
[[package]]
+name = "matrix-stdlib"
+version = "0.1.0"
+
+[[package]]
name = "memchr"
version = "2.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index f489827..d1bda86 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,3 +1,3 @@
[workspace]
resolver = "2"
-members = [ "matrix", "matrix-bin" ]
+members = [ "matrix", "matrix-bin" , "matrix-stdlib"]
diff --git a/a.mat b/a.mat
new file mode 100644
index 0000000..e689317
--- /dev/null
+++ b/a.mat
@@ -0,0 +1,5 @@
+a = 0;
+
+while a < 1000000000 { a = a + 1 };
+
+
diff --git a/matrix-bin/src/main.rs b/matrix-bin/src/main.rs
index 3ae8135..72972c6 100644
--- a/matrix-bin/src/main.rs
+++ b/matrix-bin/src/main.rs
@@ -54,6 +54,7 @@ impl<'a> State<'a> {
let compiler = CompilerBuilder::new()
.repl(repl)
.debug(args.debug)
+ .names(vm.names())
.build();
(Self { parser, vm, compiler, repl }, file)
diff --git a/matrix-stdlib/Cargo.toml b/matrix-stdlib/Cargo.toml
new file mode 100644
index 0000000..5140bfa
--- /dev/null
+++ b/matrix-stdlib/Cargo.toml
@@ -0,0 +1,8 @@
+[package]
+name = "matrix-stdlib"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
diff --git a/matrix-stdlib/src/lib.rs b/matrix-stdlib/src/lib.rs
new file mode 100644
index 0000000..7d12d9a
--- /dev/null
+++ b/matrix-stdlib/src/lib.rs
@@ -0,0 +1,14 @@
+pub fn add(left: usize, right: usize) -> usize {
+ left + right
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn it_works() {
+ let result = add(2, 2);
+ assert_eq!(result, 4);
+ }
+}
diff --git a/matrix/src/ast.rs b/matrix/src/ast.rs
index 594cd48..19a4d04 100644
--- a/matrix/src/ast.rs
+++ b/matrix/src/ast.rs
@@ -31,7 +31,6 @@ pub enum BinaryOp {
LessEquals,
GreaterThan,
LessThan,
- Range,
}
#[derive(Debug, Clone, PartialEq)]
@@ -46,7 +45,7 @@ pub enum Expr {
Index(Box<Expr>, Vec<Expr>),
FnCall(Box<Expr>, Vec<Expr>),
- FieldAccess(Box<Expr>, Box<Expr>),
+ FieldAccess(Box<Expr>, Rc<str>),
List(InlineList),
Matrix(InlineMatrix),
@@ -60,7 +59,6 @@ pub enum Expr {
If(Box<Expr>, Box<Expr>, Option<Box<Expr>>),
Function(Rc<str>, Vec<Rc<str>>, Box<Expr>),
-
Loop(Box<Expr>),
While(Box<Expr>, Box<Expr>),
DoWhile(Box<Expr>, Box<Expr>),
@@ -178,10 +176,9 @@ pub fn optimize(expr: Expr) -> Result<Expr> {
.map(optimize)
.collect::<Result<Vec<Expr>>>()?)
}
- E::FieldAccess(key, val) => {
- let key = optimize(*key)?;
- let val = optimize(*val)?;
- E::FieldAccess(Box::new(key), Box::new(val))
+ E::FieldAccess(expr, ident) => {
+ let expr = optimize(*expr)?;
+ E::FieldAccess(Box::new(expr), ident)
},
E::List(list) =>
E::List(list.into_iter()
@@ -333,7 +330,6 @@ impl From<Token> for BinaryOp {
Divide => Self::Divide,
Modulo => Self::Modulo,
Power => Self::Power,
- Range => Self::Range,
_ => panic!("aaaaa")
}
}
diff --git a/matrix/src/chunk.rs b/matrix/src/chunk.rs
index 3906535..276ffe3 100644
--- a/matrix/src/chunk.rs
+++ b/matrix/src/chunk.rs
@@ -71,6 +71,8 @@ pub enum Instruction {
NewTable(u16),
NewMatrix(u16, u8),
+ Field(u16),
+ StoreField(u16),
Index(u8),
StoreIndex(u8),
@@ -112,6 +114,8 @@ impl Display for Instruction {
JumpFalse(idx) => write!(f, "jumpf \x1b[33m{idx}\x1b[0m"),
Call(arity) => write!(f, "call \x1b[35m{arity}\x1b[0m"),
Return => write!(f, "return"),
+ Field(name_idx) => write!(f, "field \x1b[33m{name_idx}\x1b[0m"),
+ StoreField(name_idx) => write!(f, "store field \x1b[33m{name_idx}\x1b[0m"),
}
}
}
diff --git a/matrix/src/compiler.rs b/matrix/src/compiler.rs
index 49594ad..5531d7e 100644
--- a/matrix/src/compiler.rs
+++ b/matrix/src/compiler.rs
@@ -7,10 +7,11 @@ use Expr as E;
pub struct CompilerBuilder<'c> {
globals: Rc<RefCell<Vec<Rc<str>>>>,
+ names: Rc<RefCell<Vec<Rc<str>>>>,
repl: bool,
debug: bool,
name: Rc<str>,
- parent: Option<&'c Compiler<'c>>
+ parent: Option<&'c Compiler<'c>>,
}
impl<'c> CompilerBuilder<'c> {
@@ -22,6 +23,7 @@ impl<'c> CompilerBuilder<'c> {
debug: false,
name: "<root>".into(),
parent: None,
+ names: Rc::new(RefCell::new(Vec::new()))
}
}
@@ -40,6 +42,11 @@ impl<'c> CompilerBuilder<'c> {
self
}
+ pub fn names(mut self, names: Rc<RefCell<Vec<Rc<str>>>>) -> Self {
+ self.names = names;
+ self
+ }
+
pub fn parent(mut self, parent: &'c Compiler) -> Self {
self.parent = Some(parent);
self
@@ -53,6 +60,7 @@ impl<'c> CompilerBuilder<'c> {
pub fn build(self) -> Compiler<'c> {
Compiler {
name: self.name,
+ names: self.names,
parent: self.parent,
globals: self.globals,
repl: self.repl,
@@ -73,6 +81,7 @@ pub struct Compiler<'c> {
locals: Vec<Rc<Local>>,
globals: Rc<RefCell<Vec<Rc<str>>>>,
+ names: Rc<RefCell<Vec<Rc<str>>>>,
root_is_block: bool,
@@ -207,6 +216,12 @@ impl<'c> Compiler<'c> {
None
}
+ fn get_name(&mut self, name: Rc<str>) -> usize {
+ let idx = self.names.borrow().len();
+ self.names.borrow_mut().push(name);
+ idx
+ }
+
fn emit_const(&mut self, val: Value) {
// TODO: find constant if already exists
self.chunk.constants.push(val);
@@ -244,7 +259,7 @@ impl<'c> Compiler<'c> {
fn compile_expr(&mut self, expr: &Expr) -> Result<()> {
match expr {
- E::NoOp => {},
+ E::NoOp => self.emit(I::Nil),
E::If(cond, ifb, elseb) => {
self.compile_expr(cond)?;
let jmpidx = self.emit_temp();
@@ -375,6 +390,18 @@ impl<'c> Compiler<'c> {
self.emit(I::CreateLocal);
}
},
+ E::Index(expr, params) => {
+ self.compile_expr(expr)?;
+ for param in params {
+ self.compile_expr(param)?;
+ }
+ self.emit(I::StoreIndex(params.len() as u8));
+ },
+ E::FieldAccess(expr, ident) => {
+ self.compile_expr(expr)?;
+ let name = self.get_name(ident.clone());
+ self.emit(I::StoreField(name as u16));
+ }
_ => return Err(self::Error::InvAssign(*lhs.clone()).into())
}
}
@@ -387,7 +414,13 @@ impl<'c> Compiler<'c> {
self.compile_expr(rhs)?;
self.emit(I::BinaryOp(*op));
},
- E::Index(_, _) => return Err(self::Error::NotImplemented("indexing").into()),
+ E::Index(expr, params) => {
+ self.compile_expr(expr)?;
+ for param in params {
+ self.compile_expr(param)?;
+ }
+ self.emit(I::Index(params.len() as u8))
+ },
E::FnCall(fun, params) => {
for expr in params {
self.compile_expr(expr)?;
@@ -395,7 +428,11 @@ impl<'c> Compiler<'c> {
self.compile_expr(fun)?;
self.emit(I::Call(params.len() as u8));
},
- E::FieldAccess(_, _) => return Err(self::Error::NotImplemented("filed access").into()),
+ E::FieldAccess(expr, field) => {
+ self.compile_expr(expr)?;
+ let idx = self.get_name(field.clone());
+ self.emit(I::Field(idx as u16))
+ }
E::List(list) => {
for expr in list {
self.compile_expr(expr)?;
diff --git a/matrix/src/gc.rs b/matrix/src/gc.rs
index 85129dc..98d3228 100644
--- a/matrix/src/gc.rs
+++ b/matrix/src/gc.rs
@@ -1,112 +1,126 @@
-use std::cmp::Ordering;
-use std::fmt::{Debug, Display};
-use std::marker::PhantomData;
-use std::ops::{Deref, DerefMut};
-use std::ptr::NonNull;
-use std::rc::Rc;
+use std::{ops::{Index, IndexMut, Deref, DerefMut}, marker::PhantomData, ptr::NonNull, fmt::{Debug, Display}};
pub struct Gc<T> {
ptr: NonNull<GcInner<T>>,
- phantom: PhantomData<GcInner<T>>,
+ phantom: PhantomData<GcInner<T>>
}
-pub struct GcInner<T> {
+struct GcInner<T> {
rc: usize,
- data: T,
+ data: T
}
impl<T> Gc<T> {
- pub fn new(data: T) -> Gc<T> {
+ pub fn new(data: T) -> Self {
let boxed = Box::new(GcInner {
rc: 1,
data,
});
Self {
ptr: NonNull::new(Box::into_raw(boxed)).unwrap(),
- phantom: PhantomData,
+ phantom: PhantomData
}
}
}
-impl<T: Clone> From<Rc<T>> for Gc<T> {
- fn from(value: Rc<T>) -> Self {
- Self::new(Rc::unwrap_or_clone(value))
+impl <T: Clone> Gc<T> {
+ pub fn clone_inside(&mut self) -> Self {
+ unsafe {
+ let data = self.ptr.as_mut().data.clone();
+ Self::new(data)
+ }
}
}
impl<T> From<T> for Gc<T> {
fn from(value: T) -> Self {
- Self::new(value)
+ Gc::new(value)
}
}
-impl<T> Deref for Gc<T> {
- type Target = T;
- fn deref(&self) -> &T {
- let inner = unsafe { self.ptr.as_ref() };
- &inner.data
+impl<T: IndexMut<Idx>, Idx> IndexMut<Idx> for Gc<T> {
+ fn index_mut(&mut self, index: Idx) -> &mut Self::Output {
+ self.deref_mut().index_mut(index)
}
}
-impl<T: Debug> Debug for Gc<T> {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- let inner = unsafe { self.ptr.as_ref() };
- write!(f, "{:?}", inner.data)
+impl<T: Index<Idx>, Idx> Index<Idx> for Gc<T> {
+ type Output = T::Output;
+
+ fn index(&self, index: Idx) -> &Self::Output {
+ self.deref().index(index)
}
}
-impl<T: Display> Display for Gc<T> {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- let inner = unsafe { self.ptr.as_ref() };
- write!(f, "{}", inner.data)
+impl<T> DerefMut for Gc<T> {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ unsafe {
+ &mut self.ptr.as_mut().data
+ }
}
}
-impl<T: PartialEq> PartialEq for Gc<T> {
- fn eq(&self, other: &Self) -> bool {
- let inner = unsafe { self.ptr.as_ref() };
- let other = unsafe { other.ptr.as_ref() };
- inner.data == other.data
+impl<T> Deref for Gc<T> {
+ type Target = T;
+
+ fn deref(&self) -> &Self::Target {
+ unsafe {
+ &self.ptr.as_ref().data
+ }
}
}
-impl<T: PartialOrd> PartialOrd for Gc<T> {
- fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
- let inner = unsafe { self.ptr.as_ref() };
- let other = unsafe { other.ptr.as_ref() };
- inner.data.partial_cmp(&other.data)
+impl <T: PartialEq> PartialEq for Gc<T> {
+ fn eq(&self, other: &Self) -> bool {
+ self.deref().eq(other.deref())
}
}
-impl<T: Clone> DerefMut for Gc<T> {
- fn deref_mut(&mut self) -> &mut Self::Target {
- let inner = unsafe { self.ptr.as_mut() };
- if inner.rc > 1 {
- *self = Self::new(inner.data.clone());
- }
- &mut inner.data
+impl <T: Iterator> Iterator for Gc<T> {
+ type Item = T::Item;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.deref_mut().next()
}
}
+impl<T: Eq> Eq for Gc<T> {}
+
impl<T> Clone for Gc<T> {
fn clone(&self) -> Self {
- let inner = unsafe { self.ptr.as_ptr().as_mut().unwrap() };
- inner.rc += 1;
- Self {
- ptr: self.ptr,
- phantom: PhantomData,
+ unsafe {
+ let inner = self.ptr.as_ptr().as_mut().unwrap();
+ inner.rc += 1;
+
+ Self {
+ ptr: self.ptr,
+ phantom: PhantomData
+ }
}
}
}
impl<T> Drop for Gc<T> {
fn drop(&mut self) {
- let inner = unsafe { self.ptr.as_mut() };
- inner.rc -= 1;
- if inner.rc > 0 {
- return;
+ unsafe {
+ let inner = self.ptr.as_mut();
+ if inner.rc > 1 {
+ inner.rc -= 1;
+ } else {
+ let _ = Box::from_raw(self.ptr.as_ptr());
+ }
}
- unsafe { let _ = Box::from_raw(self.ptr.as_ptr()); }
}
}
+impl<T: Debug> Debug for Gc<T> {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ write!(f, "{:?}", self.deref())
+ }
+}
+
+impl<T: Display> Display for Gc<T> {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ write!(f, "{}", self.deref())
+ }
+}
diff --git a/matrix/src/lex.rs b/matrix/src/lex.rs
index 953a495..ab0359b 100644
--- a/matrix/src/lex.rs
+++ b/matrix/src/lex.rs
@@ -38,9 +38,7 @@ pub enum Token {
LeftBrack,
RightBrack,
LeftBrace,
- LeftLeftBrace,
RightBrace,
- RightRightBrace,
Assign,
Access,
SemiColon,
@@ -48,6 +46,15 @@ pub enum Token {
ThinArrow,
Comma,
Range,
+ Colon,
+
+ // math
+ Regex(RegexToken),
+ Int(i64),
+ Float(f64),
+ Complex(f64),
+ String(Rc<str>),
+ Ident(Rc<str>),
// equality
Equal,
@@ -67,14 +74,6 @@ pub enum Token {
BitwiseOr,
BitwiseXor,
- // math
- Regex(RegexToken),
- Int(i64),
- Float(f64),
- Complex(f64),
- String(Rc<str>),
- Ident(Rc<str>),
-
Add,
Subtract,
Multiply,
@@ -82,6 +81,22 @@ pub enum Token {
Modulo,
Power,
+ AssignAnd,
+ AssignOr,
+
+ AssignBitwiseShiftLeft,
+ AssignBitwiseShiftRight,
+ AssignBitwiseAnd,
+ AssignBitwiseOr,
+ AssignBitwiseXor,
+
+ AssignAdd,
+ AssignSubtract,
+ AssignMultiply,
+ AssignDivide,
+ AssignModulo,
+ AssignPower,
+
// keywords
If,
Else,
@@ -193,7 +208,7 @@ impl Lexer {
}
fn skip_whitespace(&mut self, ignore_newlines: bool) {
- while self.peek().is_whitespace() && (!ignore_newlines || self.peek() != '\n') {
+ while self.peek().is_whitespace() && (ignore_newlines || self.peek() != '\n') {
self.next();
}
}
@@ -420,42 +435,62 @@ impl Lexer {
}
Ok(match char {
+ '\n' => SemiColon,
'(' => LeftParen,
')' => RightParen,
'[' => LeftBrack,
']' => RightBrack,
- '{' => {
+ '{' => LeftBrace,
+ '}' => RightBrace,
+ ':' => Colon,
+ ';' => SemiColon,
+ '+' => {
match next {
- '{' => {
+ '=' => {
self.next();
- LeftLeftBrace
+ AssignAdd
}
- _ => LeftBrace
+ _ => Add
}
},
- '}' => {
+ '/' => {
match next {
- '}' => {
+ '=' => {
self.next();
- RightRightBrace
+ AssignDivide
}
- _ => RightBrace
+ _ => Divide
+ }
+ },
+ '%' => {
+ match next {
+ '=' => {
+ self.next();
+ AssignModulo
+ }
+ _ => Modulo
}
},
- ';' => SemiColon,
- '+' => Add,
',' => Comma,
'*' => {
match next {
'*' => {
self.next();
- Power
+ match self.peek() {
+ '=' => {
+ self.next();
+ AssignPower
+ },
+ _ => Power
+ }
+ },
+ '=' => {
+ self.next();
+ AssignMultiply
}
_ => Multiply
}
},
- '/' => Divide,
- '%' => Modulo,
'!' => {
match next {
'=' => {
@@ -469,8 +504,18 @@ impl Lexer {
match next {
'&' => {
self.next();
- And
- }
+ match self.peek() {
+ '=' => {
+ self.next();
+ AssignAnd
+ },
+ _ => And
+ }
+ },
+ '=' => {
+ self.next();
+ AssignBitwiseAnd
+ },
_ => BitwiseAnd
}
},
@@ -478,8 +523,18 @@ impl Lexer {
match next {
'|' => {
self.next();
- Or
- }
+ match self.peek() {
+ '=' => {
+ self.next();
+ AssignOr
+ },
+ _ => Or
+ }
+ },
+ '=' => {
+ self.next();
+ AssignBitwiseOr
+ },
_ => BitwiseOr
}
},
@@ -488,7 +543,11 @@ impl Lexer {
'>' => {
self.next();
ThinArrow
- }
+ },
+ '=' => {
+ self.next();
+ AssignSubtract
+ },
_ => Subtract
}
},
@@ -509,7 +568,13 @@ impl Lexer {
match next {
'>' => {
self.next();
- BitwiseShiftRight
+ match self.peek() {
+ '=' => {
+ self.next();
+ AssignBitwiseShiftRight
+ },
+ _ => BitwiseShiftRight
+ }
}
'=' => {
self.next();
@@ -522,7 +587,13 @@ impl Lexer {
match next {
'<' => {
self.next();
- BitwiseShiftLeft
+ match self.peek() {
+ '=' => {
+ self.next();
+ AssignBitwiseShiftLeft
+ },
+ _ => BitwiseShiftLeft
+ }
}
'=' => {
self.next();
@@ -531,7 +602,15 @@ impl Lexer {
_ => LessThan
}
},
- '^' => BitwiseXor,
+ '^' => {
+ match next {
+ '=' => {
+ self.next();
+ AssignBitwiseXor
+ },
+ _ => BitwiseXor
+ }
+ }
'\'' | '\"' => String(self.lex_string(char)?),
'r' => {
match next {
diff --git a/matrix/src/parse.rs b/matrix/src/parse.rs
index 046b86d..4e1de2c 100644
--- a/matrix/src/parse.rs
+++ b/matrix/src/parse.rs
@@ -1,7 +1,7 @@
use std::{fmt::Display, rc::Rc};
use num_complex::Complex64;
-use crate::{lex::{Lexer, self, Token}, ast::{Expr, BinaryOp, UnaryOp, optimize}, gc::Gc, value::{Value, self}, Result};
+use crate::{lex::{Lexer, self, Token}, ast::{Expr, BinaryOp, UnaryOp, optimize}, value::{Value, self}, Result};
use Value as V;
use Expr as E;
@@ -230,9 +230,10 @@ impl Parser {
}
fn parse_table(&mut self) -> Result<Expr> {
- self.force_token(T::LeftLeftBrace)?;
+ self.force_token(T::Colon)?;
+ self.force_token(T::LeftBrace)?;
let mut table = Vec::new();
- if self.lexer.peek_token()? == T::RightRightBrace {
+ if self.lexer.peek_token()? == T::RightBrace {
self.lexer.next_token()?;
return Ok(E::Table(table))
}
@@ -244,7 +245,7 @@ impl Parser {
let next = self.lexer.next_token()?;
match next {
T::Comma => continue,
- T::RightRightBrace => break,
+ T::RightBrace => break,
_ => return Err(Error::UnexpectedToken(next).into())
}
}
@@ -402,7 +403,7 @@ impl Parser {
T::Int(i) => E::Literal(V::Int(i)),
T::Float(f) => E::Literal(V::Float(f)),
T::Complex(c) => E::Literal(V::Complex(Complex64::new(0.0, c))),
- T::Regex(r) => E::Literal(V::Regex(Gc::new(r.into()))),
+ T::Regex(r) => E::Literal(V::Regex(Rc::new(r.into()))),
T::String(s) => E::Literal(V::String(s.to_string().into())),
T::True => E::Literal(V::Bool(true)),
T::False => E::Literal(V::Bool(false)),
@@ -431,7 +432,7 @@ impl Parser {
Ok(E::Continue)
},
LeftBrack => self.parse_matrix(),
- LeftLeftBrace => self.parse_table(),
+ Colon => self.parse_table(),
LeftParen => self.parse_paren(),
_ => self.parse_value(),
}
@@ -444,8 +445,8 @@ impl Parser {
match tok {
T::Access => {
self.force_token(T::Access)?;
- let temp = self.parse_term()?;
- expr = E::FieldAccess(Box::new(expr), Box::new(temp));
+ let temp = self.parse_ident()?;
+ expr = E::FieldAccess(Box::new(expr), temp);
},
_ => break
}
@@ -563,13 +564,66 @@ impl Parser {
}
fn parse_expr(&mut self) -> Result<Expr> {
+ use BinaryOp as B;
let expr = self.parse_expr_or()?;
let tok = self.lexer.peek_token_nl()?;
Ok(match tok {
T::Assign => {
self.lexer.next_token_nl()?;
- E::Assign(Box::new(expr),Box::new(self.parse_expr()?))
- }
+ E::Assign(Box::new(expr.clone()),Box::new(self.parse_expr()?))
+ },
+ T::AssignAnd => {
+ self.lexer.next_token_nl()?;
+ E::Assign(Box::new(expr.clone()),Box::new(E::And(Box::new(expr), Box::new(self.parse_expr()?))))
+ },
+ T::AssignOr => {
+ self.lexer.next_token_nl()?;
+ E::Assign(Box::new(expr.clone()),Box::new(E::Or(Box::new(expr), Box::new(self.parse_expr()?))))
+ },
+ T::AssignAdd => {
+ self.lexer.next_token_nl()?;
+ E::Assign(Box::new(expr.clone()),Box::new(E::BinaryOp(Box::new(expr), Box::new(self.parse_expr()?), B::Add)))
+ },
+ T::AssignSubtract => {
+ self.lexer.next_token_nl()?;
+ E::Assign(Box::new(expr.clone()),Box::new(E::BinaryOp(Box::new(expr), Box::new(self.parse_expr()?), B::Subtract)))
+ },
+ T::AssignMultiply => {
+ self.lexer.next_token_nl()?;
+ E::Assign(Box::new(expr.clone()),Box::new(E::BinaryOp(Box::new(expr), Box::new(self.parse_expr()?), B::Multiply)))
+ },
+ T::AssignDivide => {
+ self.lexer.next_token_nl()?;
+ E::Assign(Box::new(expr.clone()),Box::new(E::BinaryOp(Box::new(expr), Box::new(self.parse_expr()?), B::Divide)))
+ },
+ T::AssignModulo => {
+ self.lexer.next_token_nl()?;
+ E::Assign(Box::new(expr.clone()),Box::new(E::BinaryOp(Box::new(expr), Box::new(self.parse_expr()?), B::Modulo)))
+ },
+ T::AssignPower => {
+ self.lexer.next_token_nl()?;
+ E::Assign(Box::new(expr.clone()),Box::new(E::BinaryOp(Box::new(expr), Box::new(self.parse_expr()?), B::Power)))
+ },
+ T::AssignBitwiseAnd => {
+ self.lexer.next_token_nl()?;
+ E::Assign(Box::new(expr.clone()),Box::new(E::BinaryOp(Box::new(expr), Box::new(self.parse_expr()?), B::BitwiseAnd)))
+ },
+ T::AssignBitwiseOr => {
+ self.lexer.next_token_nl()?;
+ E::Assign(Box::new(expr.clone()),Box::new(E::BinaryOp(Box::new(expr), Box::new(self.parse_expr()?), B::BitwiseOr)))
+ },
+ T::AssignBitwiseXor => {
+ self.lexer.next_token_nl()?;
+ E::Assign(Box::new(expr.clone()),Box::new(E::BinaryOp(Box::new(expr), Box::new(self.parse_expr()?), B::BitwiseXor)))
+ },
+ T::AssignBitwiseShiftLeft => {
+ self.lexer.next_token_nl()?;
+ E::Assign(Box::new(expr.clone()),Box::new(E::BinaryOp(Box::new(expr), Box::new(self.parse_expr()?), B::BitwiseShiftLeft)))
+ },
+ T::AssignBitwiseShiftRight => {
+ self.lexer.next_token_nl()?;
+ E::Assign(Box::new(expr.clone()),Box::new(E::BinaryOp(Box::new(expr), Box::new(self.parse_expr()?), B::BitwiseShiftRight)))
+ },
_ => expr
})
}
diff --git a/matrix/src/value.rs b/matrix/src/value.rs
index 3ff7e56..b7a8218 100644
--- a/matrix/src/value.rs
+++ b/matrix/src/value.rs
@@ -4,7 +4,7 @@ use num_complex::Complex64;
use num_rational::Rational64;
use regex::Regex;
-use crate::{ast::{Expr, BinaryOp, UnaryOp}, gc::Gc, chunk::Function, Result};
+use crate::{ast::{Expr, BinaryOp, UnaryOp}, chunk::Function, Result, gc::Gc};
pub type List = Vec<Value>;
pub type Matrix = (usize, usize, Vec<Value>);
@@ -43,12 +43,14 @@ pub enum Error {
Exponent(Value, Value),
Compare(Value, Value),
IndexOutOfBounds(usize, usize),
- Index(Value, Value),
+ CannotIndex(Value),
+ BadIndex(Value, Value),
Concat(Value, Value),
Bitwise(Value, Value),
DivideByZero,
ZeroExpZero,
CannotHash(Value),
+ FieldAccess(Value),
}
impl Display for self::Error {
@@ -64,12 +66,14 @@ impl Display for self::Error {
Exponent(a, b) => write!(f, "cannot compute {a:?} pow {b:?}"),
Compare(a, b) => write!(f, "cannot compare {a:?} and {b:?}"),
IndexOutOfBounds(a, b) => write!(f, "index {a} out of bounds for list of length {b}"),
- Index(a, b) => write!(f, "cannot index {a:?} with {b:?}"),
+ BadIndex(a, b) => write!(f, "cannot index {a:?} with {b:?}"),
+ CannotIndex(a) => write!(f, "cannot index {a:?}"),
Concat(a, b) => write!(f, "cannot concat {a:?} and {b:?}"),
Bitwise(a, b) => write!(f, "cannot bitwise between {a:?} and {b:?}"),
DivideByZero => write!(f, "attempted to divide by zero"),
ZeroExpZero => write!(f, "cannot exponent zero with zero"),
CannotHash(v) => write!(f, "cannot hash {v:?}"),
+ FieldAccess(a) => write!(f, "{a:?} cannot be field accessed"),
}
}
}
@@ -84,8 +88,8 @@ pub enum Value {
Float(f64),
Ratio(Rational64),
Complex(Complex64),
- Regex(Gc<Regex>),
- String(Gc<String>),
+ Regex(Rc<Regex>),
+ String(Rc<String>),
List(Gc<List>),
Matrix(Gc<Matrix>),
Table(Gc<Table>),
@@ -153,21 +157,21 @@ impl Value {
Float(l) => format!("{l}"),
Ratio(r) => format!("{r}"),
Complex(c) => format!("{c}"),
- Regex(r) => format!("{r}"),
+ Regex(r) => format!("/{r}/"),
String(s) => format!("{s}"),
List(l) => {
- let mut str = "[ ".to_string();
+ let mut str = "[".to_string();
for (i, el) in l.iter().enumerate() {
if i != 0 {
str.push_str(" ");
}
str.push_str(&el.boring_print());
}
- str.push_str(" ]");
+ str.push_str("]");
str
},
Matrix(m) => {
- let mut str = "[[ ".to_string();
+ let mut str = "[[".to_string();
for (i, el) in m.2.iter().enumerate() {
if i != 0 {
if (i % m.1) == 0 {
@@ -178,11 +182,11 @@ impl Value {
}
str.push_str(&el.boring_print());
}
- str.push_str(" ]]");
+ str.push_str("]]");
str
},
Table(t) => {
- let mut str = "{{ ".to_string();
+ let mut str = "{".to_string();
for (i, (key, val)) in t.0.iter().enumerate() {
if i != 0 {
str.push_str(", ");
@@ -191,7 +195,7 @@ impl Value {
str.push_str(" = ");
str.push_str(&val.boring_print());
}
- str.push_str(" }}");
+ str.push_str("}");
str
},
Function(fun) => {
@@ -212,18 +216,18 @@ impl Value {
Regex(_) => format!("\x1b[31m{}\x1b[0m", self.boring_print()),
String(_) => format!("\x1b[32m'{}'\x1b[0m", self.boring_print()),
List(l) => {
- let mut str = "[ ".to_string();
+ let mut str = "[".to_string();
for (i, el) in l.iter().enumerate() {
if i != 0 {
str.push_str(" ");
}
str.push_str(&el.pretty_print());
}
- str.push_str(" ]");
+ str.push_str("]");
str
},
Matrix(m) => {
- let mut str = "[[ ".to_string();
+ let mut str = "[[".to_string();
for (i, el) in m.2.iter().enumerate() {
if i != 0 {
if (i % m.1) == 0 {
@@ -234,11 +238,11 @@ impl Value {
}
str.push_str(&el.pretty_print());
}
- str.push_str(" ]]");
+ str.push_str("]]");
str
},
Table(t) => {
- let mut str = "{{ ".to_string();
+ let mut str = "{".to_string();
for (i, (key, val)) in t.0.iter().enumerate() {
if i != 0 {
str.push_str(", ");
@@ -247,7 +251,7 @@ impl Value {
str.push_str(" = ");
str.push_str(&val.pretty_print());
}
- str.push_str(" }}");
+ str.push_str("}");
str
},
Function(_) => {
@@ -295,10 +299,10 @@ impl Add for Value {
(Float(x), Float(y)) => Ok(Float(x + y)),
(Ratio(x), Ratio(y)) => Ok(Ratio(x + y)),
(Complex(x), Complex(y)) => Ok(Complex(x + y)),
- (String(str), value) => Ok(String(Gc::new(
+ (String(str), value) => Ok(String(Rc::new(
format!("{str}{}", value.boring_print())
))),
- (value, String(str)) => Ok(String(Gc::new(
+ (value, String(str)) => Ok(String(Rc::new(
format!("{}{str}", value.boring_print())
))),
(List(mut l1), List(l2)) => {
@@ -420,28 +424,18 @@ fn ipow(n: i64, d: i64, p: i64) -> Result<(i64, i64)> {
}
impl Value {
+
pub fn modulo(self, rhs: Value) -> Result<Self> {
use Value::*;
match promote(self, rhs) {
- (Int(x), Int(y)) => Ok(Int(x.rem_euclid(y))),
- (Float(x), Float(y)) => Ok(Float(x.rem_euclid(y))),
- (Ratio(_x), Ratio(_y)) => todo!("ratio modulo"),
- (Complex(_x), Complex(_y)) => todo!("complex modulo"),
+ (Int(x), Int(y)) => Ok(Int(x % y)),
+ (Float(x), Float(y)) => Ok(Float(x % y)),
+ (Ratio(x), Ratio(y)) => Ok(Ratio(x % y)),
+ (Complex(x), Complex(y)) => Ok(Complex(x % y)),
(l, r) => Err(Error::Modulo(r, l).into())
}
}
- pub fn int_div(self, rhs: Value) -> Result<Self> {
- use Value::*;
- match promote(self, rhs) {
- (Int(x), Int(y)) => Ok(Int(x.div_euclid(y))),
- (Float(x), Float(y)) => Ok(Float(x.div_euclid(y))),
- (Ratio(_x), Ratio(_y)) => todo!("ratio integer division"),
- (Complex(_x), Complex(_y)) => todo!("complex integer division"),
- (l, r) => Err(Error::Divide(l, r).into())
- }
- }
-
pub fn pow(self, rhs: Value) -> Result<Self> {
use Value::*;
if let (Ratio(x), Int(y)) = (&self, &rhs) {
@@ -518,24 +512,123 @@ impl Value {
.map_or_else(|| Err(Error::Compare(self.clone(), other.clone()).into()), Ok)
}
- pub fn store_index(&self, _other: &Vec<Self>, _value: &Self) -> Result<()> {
- todo!()
+ fn index_single(&self, index: &Value) -> Result<Self> {
+ use Value as V;
+ match (self, index) {
+ (V::Table(t), index) => {
+ Ok(t.get(index)?.unwrap_or(&Value::Nil).clone())
+ },
+ (V::List(l), V::Int(i)) => {
+ if *i < 0 || *i as usize >= l.len() {
+ return Err(Error::IndexOutOfBounds(*i as usize, l.len()).into())
+ }
+ Ok(l[*i as usize].clone())
+ }
+ _ => return Err(self::Error::BadIndex(self.clone(), index.clone()).into())
+ }
}
- pub fn index(&self, _other: &Vec<Self>) -> Result<Self> {
- todo!()
- //use Value::*;
- //match (self, other) {
- // (List(l), Int(i)) => {
- // if *i >= 0 && *i < l.len() as i64 {
- // Ok(l[*i as usize].clone())
- // } else {
- // Err(Error::IndexOutOfBounds(*i as usize, l.len()))
- // }
- // },
- // (l, r) => Err(Error::Index(l.clone(), r.clone()))
- //}
- }
+ fn index_multiple(&self, indexes: &Vec<Value>) -> Result<Self> {
+ use Value as V;
+ match self {
+ V::List(..) => {
+ let mut ret = Vec::new();
+ for index in indexes {
+ let res = self.index_single(index)?;
+ ret.push(res);
+ }
+ Ok(V::List(ret.into()))
+ }
+ V::Table(..) => {
+ let mut ret = ValueMap::new();
+ for index in indexes {
+ let res = self.index_single(index)?;
+ ret.insert(index.clone(), res)?;
+ }
+ Ok(V::Table(ret.into()))
+ }
+ _ => return Err(self::Error::CannotIndex(self.clone()).into())
+ }
+ }
+
+ pub fn index(&self, index: &Vec<Value>) -> Result<Self> {
+ if index.len() == 0 {
+ Ok(self.clone())
+ } else if index.len() == 1 {
+ self.index_single(&index[0])
+ } else {
+ self.index_multiple(index)
+ }
+ }
+
+ fn store_index_single(&mut self, index: &Value, store: Value) -> Result<()> {
+ use Value as V;
+ let err = self.clone();
+ match (self, index) {
+ (V::Table(t), index) => {
+ t.insert(index.clone(), store)
+ },
+ (V::List(l), V::Int(i)) => {
+ if *i < 0 || *i as usize >= l.len() {
+ return Err(Error::IndexOutOfBounds(*i as usize, l.len()).into())
+ }
+ l[*i as usize] = store;
+ Ok(())
+ }
+ _ => return Err(self::Error::BadIndex(err, index.clone()).into())
+ }
+ }
+
+ fn store_index_multiple(&mut self, indexes: &Vec<Value>, store: Value) -> Result<()> {
+ use Value as V;
+ match self {
+ V::List(..) => {
+ for index in indexes {
+ self.store_index_single(index, store.clone())?;
+ }
+ Ok(())
+ }
+ V::Table(..) => {
+ for index in indexes {
+ self.store_index_single(index, store.clone())?;
+ }
+ Ok(())
+ }
+ _ => return Err(self::Error::CannotIndex(self.clone()).into())
+ }
+ }
+
+ pub fn store_index(&mut self, index: &Vec<Value>, store: Value) -> Result<()> {
+ if index.len() == 0 {
+ Ok(())
+ } else if index.len() == 1 {
+ self.store_index_single(&index[0], store)
+ } else {
+ self.store_index_multiple(index, store)
+ }
+ }
+
+ pub fn store_field_access(&mut self, ident: &str, val: Value) -> Result<()> {
+ use Value as V;
+ match self {
+ V::Table(t) => {
+ let key = V::String(Rc::new(ident.to_string()));
+ Ok(t.insert(key, val)?)
+ },
+ _ => return Err(self::Error::FieldAccess(self.clone()).into())
+ }
+ }
+
+ pub fn field_access(&self, ident: &str) -> Result<Self> {
+ use Value as V;
+ match self {
+ V::Table(t) => {
+ let key = V::String(Rc::new(ident.to_string()));
+ Ok(t.get(&key)?.unwrap_or(&V::Nil).clone())
+ },
+ _ => return Err(self::Error::FieldAccess(self.clone()).into())
+ }
+ }
pub fn binary_op(op: BinaryOp, lhs: Value, rhs: Value) -> Result<Self> {
use BinaryOp::*;
@@ -557,7 +650,6 @@ impl Value {
LessEquals => Ok(Self::Bool(lhs <= rhs)),
GreaterThan => Ok(Self::Bool(lhs > rhs)),
LessThan => Ok(Self::Bool(lhs < rhs)),
- Range => todo!(),
}
}
diff --git a/matrix/src/vm.rs b/matrix/src/vm.rs
index d5408c9..d0729eb 100644
--- a/matrix/src/vm.rs
+++ b/matrix/src/vm.rs
@@ -1,4 +1,4 @@
-use std::{rc::Rc, fmt::{Debug, Display}, usize, ops::{Index, IndexMut}, collections::HashMap};
+use std::{rc::Rc, fmt::{Debug, Display}, usize, ops::{Index, IndexMut}, collections::HashMap, cell::RefCell};
use crate::{value::{Value, self, ValueMap}, gc::Gc, chunk::{Function, Instruction}, Result};
#[derive(Debug)]
@@ -108,6 +108,7 @@ pub struct Vm {
locals: Stack<Value>,
frames: Vec<StackFrame>,
globals: HashMap<u16, Value>,
+ names: Rc<RefCell<Vec<Rc<str>>>>,
}
impl Vm {
@@ -120,12 +121,17 @@ impl Vm {
self.stack.pop()
}
+ pub fn names(&self) -> Rc<RefCell<Vec<Rc<str>>>> {
+ self.names.clone()
+ }
+
pub fn new() -> Self {
Self {
stack: Stack::new(),
locals: Stack::new(),
frames: Vec::new(),
globals: HashMap::new(),
+ names: Rc::new(RefCell::new(Vec::new())),
}
}
@@ -135,11 +141,12 @@ impl Vm {
use Instruction::*;
let ins = frame.fun.body.code[frame.ip].clone();
frame.ip += 1;
+
match ins {
NoOp => {},
CreateLocal => self.locals.push(self.stack.pop()),
LoadLocal(idx) => {self.stack.push(self.locals[idx as usize].clone());},
- StoreLocal(idx) => self.stack[frame.bp + idx as usize] = self.pop(),
+ StoreLocal(idx) => self.locals[frame.bp + idx as usize] = self.pop(),
DiscardLocals(count) => {self.locals.truncate(self.locals.len() - count as usize)},
LoadGlobal(idx) => {
let val = self.globals
@@ -187,18 +194,6 @@ impl Vm {
let domain = list.len() / codomain;
self.push(Value::Matrix(Gc::new((domain, codomain, list.inner))));
}
- Index(count) => {
- let index = self.stack.split_off(self.stack.len() - count as usize);
- let collection = self.pop();
- let value = collection.index(&index.inner)?;
- self.stack.push(value);
- },
- StoreIndex(count) => {
- let value = self.pop();
- let index = self.stack.split_off(self.stack.len() - count as usize);
- let collection = self.pop();
- collection.store_index(&index.inner, &value)?;
- }
Jump(idx) => frame.ip = idx as usize,
JumpTrue(idx) => {
if !!self.pop() {
@@ -231,6 +226,29 @@ impl Vm {
self.push(ret);
frame = prev_frame;
},
+ Field(name_idx) => {
+ let expr = self.pop();
+ let name = self.names.borrow()[name_idx as usize].clone();
+ self.push(expr.field_access(&name)?);
+ },
+ StoreField(name_idx) => {
+ let mut expr = self.pop();
+ let value = self.pop();
+ let name = self.names.borrow()[name_idx as usize].clone();
+ expr.store_field_access(&name, value)?;
+ },
+ Index(count) => {
+ let index = self.stack.split_off(self.stack.len() - count as usize);
+ let collection = self.pop();
+ let value = collection.index(&index.inner)?;
+ self.stack.push(value);
+ },
+ StoreIndex(count) => {
+ let index = self.stack.split_off(self.stack.len() - count as usize);
+ let mut collection = self.pop();
+ let value = self.pop();
+ collection.store_index(&index.inner, value)?;
+ }
}
}
Ok(self.pop())
diff --git a/syntax_thing b/syntax_thing
new file mode 100644
index 0000000..8f48af7
--- /dev/null
+++ b/syntax_thing
@@ -0,0 +1,63 @@
+root => root_expr*
+root_expr => function
+root_expr => expr
+function => FUNCTION IDENT params block
+params => IDENT
+params => OP CP
+params => OP params_impl
+params_impl => IDENT COMMA params_impl
+params_impl => IDENT CP
+block => expr*
+expr => if_expr
+if_expr => IF math_expr block ELSE if_expr
+if_expr => IF math_expr block ELSE block
+if_expr => IF math_expr block
+expr => DO block WHILE math_expr
+expr => WHILE math_expr block
+expr => LET IDENT EQ math_expr END
+expr => LET IDENT END
+expr => IDENT EQ math_expr END
+expr => block
+expr => RETURN math_expr END
+expr => BREAK
+expr => CONTINUE
+expr => math_expr END
+math_expr => (math_expr_and OR)* math_expr_and
+math_expr_and => math_expr_and AND math_expr_and
+math_expr_and => math_expr_compare
+math_expr_compare => math_expr_compare <COMPARE> math_expr_compare
+
+power_term => power_term POWER power_term
+power_term => power_term BIT_AND power_term
+power_term => power_term BIT_OR power_term
+power_term => power_term SHIFT_LEFT power_term
+power_term => power_term SHIFT_RIGHT power_term
+power_term => term
+term => value
+term => tuple
+term => list
+term => table
+term => IDENT
+value => INT DIVIDE INT
+value => INT
+value => FLOAT
+value => COMPLEX
+value => STRING
+value => REGEX
+value => TRUE
+value => FALSE
+tuple => OP CP
+tuple => OP tuple_impl
+tuple_impl => math_expr COMMA tuple_impl
+tuple_impl => math_expr CP
+list => LBRK RBRK
+list => LBRK list_impl
+list_impl => math_expr COMMA tuple_impl
+list_impl => math_expr RBRK
+table => LBRC RBRC
+table => LBRC table_impl
+table_impl => table_key EQ math_expr COMMA table_impl
+table_impl => table_key EQ math_expr RBRC
+table_key => LBRK math_expr RBRK
+table_key => IDENT
+table_key => STRING