Compare commits
1 Commits
parser_com
...
fix_fqsn_e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5147a32c97 |
5
Cargo.lock
generated
5
Cargo.lock
generated
@@ -461,10 +461,6 @@ dependencies = [
|
|||||||
"autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "partis"
|
|
||||||
version = "0.1.0"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "phf"
|
name = "phf"
|
||||||
version = "0.7.24"
|
version = "0.7.24"
|
||||||
@@ -743,7 +739,6 @@ name = "schala"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"includedir_codegen 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"includedir_codegen 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"partis 0.1.0",
|
|
||||||
"schala-lang 0.1.0",
|
"schala-lang 0.1.0",
|
||||||
"schala-repl 0.1.0",
|
"schala-repl 0.1.0",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ authors = ["greg <greg.shuflin@protonmail.com>"]
|
|||||||
|
|
||||||
schala-repl = { path = "schala-repl" }
|
schala-repl = { path = "schala-repl" }
|
||||||
schala-lang = { path = "schala-lang/language" }
|
schala-lang = { path = "schala-lang/language" }
|
||||||
partis = { path="partis" }
|
|
||||||
# maaru-lang = { path = "maaru" }
|
# maaru-lang = { path = "maaru" }
|
||||||
# rukka-lang = { path = "rukka" }
|
# rukka-lang = { path = "rukka" }
|
||||||
# robo-lang = { path = "robo" }
|
# robo-lang = { path = "robo" }
|
||||||
|
|||||||
14
TODO.md
14
TODO.md
@@ -1,11 +1,3 @@
|
|||||||
# Plan of attack
|
|
||||||
|
|
||||||
1. modify visitor so it can handle scopes
|
|
||||||
-this is needed both to handle import scope correctly
|
|
||||||
-and also to support making FQSNs aware of function parameters
|
|
||||||
|
|
||||||
2. Once FQSNs are aware of function parameters, most of the Rc<String> things in eval.rs can go away
|
|
||||||
|
|
||||||
# TODO items
|
# TODO items
|
||||||
|
|
||||||
-use 'let' sigil in patterns for variables :
|
-use 'let' sigil in patterns for variables :
|
||||||
@@ -16,9 +8,6 @@
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
-idea: what if there was something like React jsx syntas built in? i.e. a way to automatically transform some kind of markup
|
|
||||||
into a function call, cf. `<h1 prop="arg">` -> h1(prop=arg)
|
|
||||||
|
|
||||||
## General code cleanup
|
## General code cleanup
|
||||||
- I think I can restructure the parser to get rid of most instances of expect!, at least at the beginning of a rule
|
- I think I can restructure the parser to get rid of most instances of expect!, at least at the beginning of a rule
|
||||||
DONE -experiment with storing metadata via ItemIds on AST nodes (cf. https://rust-lang.github.io/rustc-guide/hir.html, https://github.com/rust-lang/rust/blob/master/src/librustc/hir/mod.rs )
|
DONE -experiment with storing metadata via ItemIds on AST nodes (cf. https://rust-lang.github.io/rustc-guide/hir.html, https://github.com/rust-lang/rust/blob/master/src/librustc/hir/mod.rs )
|
||||||
@@ -30,9 +19,6 @@ DONE -experiment with storing metadata via ItemIds on AST nodes (cf. https://rus
|
|||||||
-look at https://gitlab.haskell.org/ghc/ghc/wikis/pattern-synonyms
|
-look at https://gitlab.haskell.org/ghc/ghc/wikis/pattern-synonyms
|
||||||
2) the non-value-returning, default one like in rustc (cf. https://github.com/rust-unofficial/patterns/blob/master/patterns/visitor.md)
|
2) the non-value-returning, default one like in rustc (cf. https://github.com/rust-unofficial/patterns/blob/master/patterns/visitor.md)
|
||||||
|
|
||||||
-parser error - should report subset of AST parsed *so far*
|
|
||||||
- what if you used python 'def' syntax to define a function? what error message makes sense here?
|
|
||||||
|
|
||||||
## Reduction
|
## Reduction
|
||||||
- make a good type for actual language builtins to avoid string comparisons
|
- make a good type for actual language builtins to avoid string comparisons
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "partis"
|
|
||||||
version = "0.1.0"
|
|
||||||
authors = ["greg <greg.shuflin@protonmail.com>"]
|
|
||||||
edition = "2018"
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
struct ParseError { }
|
|
||||||
|
|
||||||
enum ParseResult<'a, T> {
|
|
||||||
Success(T, &'a str),
|
|
||||||
Failure(ParseError),
|
|
||||||
Incomplete,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
#[test]
|
|
||||||
fn it_works() {
|
|
||||||
assert_eq!(2 + 2, 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -14,12 +14,13 @@ mod test;
|
|||||||
|
|
||||||
pub struct State<'a> {
|
pub struct State<'a> {
|
||||||
values: ScopeStack<'a, Rc<String>, ValueEntry>,
|
values: ScopeStack<'a, Rc<String>, ValueEntry>,
|
||||||
|
symbol_table_handle: SymbolTableHandle,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> State<'a> {
|
impl<'a> State<'a> {
|
||||||
pub fn new() -> State<'a> {
|
pub fn new(symbol_table_handle: SymbolTableHandle) -> State<'a> {
|
||||||
let values = ScopeStack::new(Some(format!("global")));
|
let values = ScopeStack::new(Some(format!("global")));
|
||||||
State { values }
|
State { values, symbol_table_handle }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn debug_print(&self) -> String {
|
pub fn debug_print(&self) -> String {
|
||||||
@@ -29,6 +30,7 @@ impl<'a> State<'a> {
|
|||||||
fn new_frame(&'a self, items: &'a Vec<Node>, bound_vars: &BoundVars) -> State<'a> {
|
fn new_frame(&'a self, items: &'a Vec<Node>, bound_vars: &BoundVars) -> State<'a> {
|
||||||
let mut inner_state = State {
|
let mut inner_state = State {
|
||||||
values: self.values.new_scope(None),
|
values: self.values.new_scope(None),
|
||||||
|
symbol_table_handle: self.symbol_table_handle.clone(),
|
||||||
};
|
};
|
||||||
for (bound_var, val) in bound_vars.iter().zip(items.iter()) {
|
for (bound_var, val) in bound_vars.iter().zip(items.iter()) {
|
||||||
if let Some(bv) = bound_var.as_ref() {
|
if let Some(bv) = bound_var.as_ref() {
|
||||||
@@ -67,12 +69,12 @@ fn paren_wrapped_vec(terms: impl Iterator<Item=String>) -> String {
|
|||||||
|
|
||||||
|
|
||||||
impl Node {
|
impl Node {
|
||||||
fn to_repl(&self) -> String {
|
fn to_repl(&self, symbol_table: &SymbolTable) -> String {
|
||||||
match self {
|
match self {
|
||||||
Node::Expr(e) => e.to_repl(),
|
Node::Expr(e) => e.to_repl(symbol_table),
|
||||||
Node::PrimObject { name, items, .. } if items.len() == 0 => format!("{}", name),
|
Node::PrimObject { name, items, .. } if items.len() == 0 => format!("{}", name),
|
||||||
Node::PrimObject { name, items, .. } => format!("{}{}", name, paren_wrapped_vec(items.iter().map(|x| x.to_repl()))),
|
Node::PrimObject { name, items, .. } => format!("{}{}", name, paren_wrapped_vec(items.iter().map(|x| x.to_repl(symbol_table)))),
|
||||||
Node::PrimTuple { items } => format!("{}", paren_wrapped_vec(items.iter().map(|x| x.to_repl()))),
|
Node::PrimTuple { items } => format!("{}", paren_wrapped_vec(items.iter().map(|x| x.to_repl(symbol_table)))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn is_true(&self) -> bool {
|
fn is_true(&self) -> bool {
|
||||||
@@ -97,10 +99,12 @@ impl Expr {
|
|||||||
fn to_node(self) -> Node {
|
fn to_node(self) -> Node {
|
||||||
Node::Expr(self)
|
Node::Expr(self)
|
||||||
}
|
}
|
||||||
fn to_repl(&self) -> String {
|
fn to_repl(&self, symbol_table: &SymbolTable) -> String {
|
||||||
use self::Lit::*;
|
use self::Lit::*;
|
||||||
use self::Func::*;
|
use self::Func::*;
|
||||||
|
|
||||||
|
let _ = symbol_table;
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
Expr::Lit(ref l) => match l {
|
Expr::Lit(ref l) => match l {
|
||||||
Nat(n) => format!("{}", n),
|
Nat(n) => format!("{}", n),
|
||||||
@@ -117,7 +121,7 @@ impl Expr {
|
|||||||
Expr::Constructor { type_name, arity, .. } => {
|
Expr::Constructor { type_name, arity, .. } => {
|
||||||
format!("<constructor for `{}` arity {}>", type_name, arity)
|
format!("<constructor for `{}` arity {}>", type_name, arity)
|
||||||
},
|
},
|
||||||
Expr::Tuple(exprs) => paren_wrapped_vec(exprs.iter().map(|x| x.to_repl())),
|
Expr::Tuple(exprs) => paren_wrapped_vec(exprs.iter().map(|x| x.to_repl(symbol_table))),
|
||||||
_ => format!("{:?}", self),
|
_ => format!("{:?}", self),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -152,7 +156,8 @@ impl<'a> State<'a> {
|
|||||||
for statement in ast.0 {
|
for statement in ast.0 {
|
||||||
match self.statement(statement) {
|
match self.statement(statement) {
|
||||||
Ok(Some(ref output)) if repl => {
|
Ok(Some(ref output)) if repl => {
|
||||||
acc.push(Ok(output.to_repl()))
|
let ref symbol_table = self.symbol_table_handle.borrow();
|
||||||
|
acc.push(Ok(output.to_repl(symbol_table)))
|
||||||
},
|
},
|
||||||
Ok(_) => (),
|
Ok(_) => (),
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
@@ -206,10 +211,7 @@ impl<'a> State<'a> {
|
|||||||
Node::Expr(expr) => match expr {
|
Node::Expr(expr) => match expr {
|
||||||
literal @ Lit(_) => Ok(Node::Expr(literal)),
|
literal @ Lit(_) => Ok(Node::Expr(literal)),
|
||||||
Call { box f, args } => self.call_expression(f, args),
|
Call { box f, args } => self.call_expression(f, args),
|
||||||
Sym(name) => Ok(match self.values.lookup(&name) {
|
Sym(v) => self.handle_sym(v),
|
||||||
Some(ValueEntry::Binding { val, .. }) => val.clone(),
|
|
||||||
None => return Err(format!("Could not look up symbol {}", name))
|
|
||||||
}),
|
|
||||||
Constructor { arity, ref name, tag, .. } if arity == 0 => Ok(Node::PrimObject { name: name.clone(), tag, items: vec![] }),
|
Constructor { arity, ref name, tag, .. } if arity == 0 => Ok(Node::PrimObject { name: name.clone(), tag, items: vec![] }),
|
||||||
constructor @ Constructor { .. } => Ok(Node::Expr(constructor)),
|
constructor @ Constructor { .. } => Ok(Node::Expr(constructor)),
|
||||||
func @ Func(_) => Ok(Node::Expr(func)),
|
func @ Func(_) => Ok(Node::Expr(func)),
|
||||||
@@ -261,6 +263,7 @@ impl<'a> State<'a> {
|
|||||||
}
|
}
|
||||||
let mut func_state = State {
|
let mut func_state = State {
|
||||||
values: self.values.new_scope(name.map(|n| format!("{}", n))),
|
values: self.values.new_scope(name.map(|n| format!("{}", n))),
|
||||||
|
symbol_table_handle: self.symbol_table_handle.clone(),
|
||||||
};
|
};
|
||||||
for (param, val) in params.into_iter().zip(args.into_iter()) {
|
for (param, val) in params.into_iter().zip(args.into_iter()) {
|
||||||
let val = func_state.expression(Node::Expr(val))?;
|
let val = func_state.expression(Node::Expr(val))?;
|
||||||
@@ -339,11 +342,13 @@ impl<'a> State<'a> {
|
|||||||
|
|
||||||
/* builtin functions */
|
/* builtin functions */
|
||||||
(IOPrint, &[ref anything]) => {
|
(IOPrint, &[ref anything]) => {
|
||||||
print!("{}", anything.to_repl());
|
let ref symbol_table = self.symbol_table_handle.borrow();
|
||||||
|
print!("{}", anything.to_repl(symbol_table));
|
||||||
Expr::Unit.to_node()
|
Expr::Unit.to_node()
|
||||||
},
|
},
|
||||||
(IOPrintLn, &[ref anything]) => {
|
(IOPrintLn, &[ref anything]) => {
|
||||||
println!("{}", anything.to_repl());
|
let ref symbol_table = self.symbol_table_handle.borrow();
|
||||||
|
println!("{}", anything.to_repl(symbol_table));
|
||||||
Expr::Unit.to_node()
|
Expr::Unit.to_node()
|
||||||
},
|
},
|
||||||
(IOGetLine, &[]) => {
|
(IOGetLine, &[]) => {
|
||||||
@@ -452,4 +457,46 @@ impl<'a> State<'a> {
|
|||||||
}
|
}
|
||||||
Err(format!("{:?} failed pattern match", cond))
|
Err(format!("{:?} failed pattern match", cond))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO if I don't need to lookup by name here...
|
||||||
|
fn handle_sym(&mut self, name: Rc<String>) -> EvalResult<Node> {
|
||||||
|
use self::ValueEntry::*;
|
||||||
|
use self::Func::*;
|
||||||
|
//TODO add a layer of indirection here to talk to the symbol table first, and only then look up
|
||||||
|
//in the values table
|
||||||
|
|
||||||
|
let symbol_table = self.symbol_table_handle.borrow();
|
||||||
|
let value = symbol_table.lookup_by_fqsn(&fqsn!(name ; tr));
|
||||||
|
Ok(match value {
|
||||||
|
Some(Symbol { local_name, spec, .. }) => match spec {
|
||||||
|
//TODO I'll need this type_name later to do a table lookup
|
||||||
|
SymbolSpec::DataConstructor { type_name: _type_name, type_args, .. } => {
|
||||||
|
if type_args.len() == 0 {
|
||||||
|
Node::PrimObject { name: local_name.clone(), tag: 0, items: vec![] }
|
||||||
|
} else {
|
||||||
|
return Err(format!("This data constructor thing not done"))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
SymbolSpec::Func(_) => match self.values.lookup(&name) {
|
||||||
|
Some(Binding { val: Node::Expr(Expr::Func(UserDefined { name, params, body })), .. }) => {
|
||||||
|
Node::Expr(Expr::Func(UserDefined { name: name.clone(), params: params.clone(), body: body.clone() }))
|
||||||
|
},
|
||||||
|
_ => unreachable!(),
|
||||||
|
},
|
||||||
|
SymbolSpec::RecordConstructor { .. } => return Err(format!("This shouldn't be a record!")),
|
||||||
|
SymbolSpec::Binding => match self.values.lookup(&name) {
|
||||||
|
Some(Binding { val, .. }) => val.clone(),
|
||||||
|
None => return Err(format!("Symbol {} exists in symbol table but not in evaluator table", name))
|
||||||
|
}
|
||||||
|
SymbolSpec::Type { name } => return Err(format!("Symbol {} not in scope", name)),
|
||||||
|
},
|
||||||
|
//TODO ideally this should be returning a runtime error if this is ever None, but it's not
|
||||||
|
//handling all bindings correctly yet
|
||||||
|
//None => return Err(format!("Couldn't find value {}", name)),
|
||||||
|
None => match self.values.lookup(&name) {
|
||||||
|
Some(Binding { val, .. }) => val.clone(),
|
||||||
|
None => return Err(format!("Couldn't find value {}", name)),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,14 +12,14 @@ fn evaluate_all_outputs(input: &str) -> Vec<Result<String, String>> {
|
|||||||
let (mut ast, source_map) = crate::util::quick_ast(input);
|
let (mut ast, source_map) = crate::util::quick_ast(input);
|
||||||
let source_map = Rc::new(RefCell::new(source_map));
|
let source_map = Rc::new(RefCell::new(source_map));
|
||||||
let symbol_table = Rc::new(RefCell::new(SymbolTable::new(source_map)));
|
let symbol_table = Rc::new(RefCell::new(SymbolTable::new(source_map)));
|
||||||
symbol_table.borrow_mut().add_top_level_symbols(&ast).unwrap();
|
let mut state = State::new(symbol_table);
|
||||||
|
state.symbol_table_handle.borrow_mut().add_top_level_symbols(&ast).unwrap();
|
||||||
{
|
{
|
||||||
let mut scope_resolver = ScopeResolver::new(symbol_table.clone());
|
let mut scope_resolver = ScopeResolver::new(state.symbol_table_handle.clone());
|
||||||
let _ = scope_resolver.resolve(&mut ast);
|
let _ = scope_resolver.resolve(&mut ast);
|
||||||
}
|
}
|
||||||
|
|
||||||
let reduced = reduce(&ast, &symbol_table.borrow());
|
let reduced = reduce(&ast, &state.symbol_table_handle.borrow());
|
||||||
let mut state = State::new();
|
|
||||||
let all_output = state.evaluate(reduced, true);
|
let all_output = state.evaluate(reduced, true);
|
||||||
all_output
|
all_output
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#![feature(trace_macros)]
|
#![feature(trace_macros)]
|
||||||
|
#![feature(custom_attribute)]
|
||||||
//#![feature(unrestricted_attribute_tokens)]
|
//#![feature(unrestricted_attribute_tokens)]
|
||||||
#![feature(slice_patterns, box_patterns, box_syntax)]
|
#![feature(slice_patterns, box_patterns, box_syntax)]
|
||||||
|
|
||||||
|
|||||||
@@ -991,7 +991,7 @@ impl Parser {
|
|||||||
self.token_handler.next();
|
self.token_handler.next();
|
||||||
Pattern::Literal(PatternLiteral::BoolPattern(false))
|
Pattern::Literal(PatternLiteral::BoolPattern(false))
|
||||||
},
|
},
|
||||||
StrLiteral { s, .. } => {
|
StrLiteral(s) => {
|
||||||
self.token_handler.next();
|
self.token_handler.next();
|
||||||
Pattern::Literal(PatternLiteral::StringPattern(s))
|
Pattern::Literal(PatternLiteral::StringPattern(s))
|
||||||
},
|
},
|
||||||
@@ -1140,7 +1140,7 @@ impl Parser {
|
|||||||
let id = self.id_store.fresh();
|
let id = self.id_store.fresh();
|
||||||
Ok(Expression::new(id, BoolLiteral(false)))
|
Ok(Expression::new(id, BoolLiteral(false)))
|
||||||
},
|
},
|
||||||
StrLiteral {s, ..} => {
|
StrLiteral(s) => {
|
||||||
self.token_handler.next();
|
self.token_handler.next();
|
||||||
let id = self.id_store.fresh();
|
let id = self.id_store.fresh();
|
||||||
Ok(Expression::new(id, StringLiteral(s.clone())))
|
Ok(Expression::new(id, StringLiteral(s.clone())))
|
||||||
|
|||||||
@@ -42,9 +42,9 @@ pub enum Stmt {
|
|||||||
pub enum Expr {
|
pub enum Expr {
|
||||||
Unit,
|
Unit,
|
||||||
Lit(Lit),
|
Lit(Lit),
|
||||||
Sym(Rc<String>), //a Sym is anything that can be looked up by name at runtime - i.e. a function or variable address
|
|
||||||
Tuple(Vec<Expr>),
|
Tuple(Vec<Expr>),
|
||||||
Func(Func),
|
Func(Func),
|
||||||
|
Sym(FullyQualifiedSymbolName),
|
||||||
Constructor {
|
Constructor {
|
||||||
type_name: Rc<String>,
|
type_name: Rc<String>,
|
||||||
name: Rc<String>,
|
name: Rc<String>,
|
||||||
@@ -56,7 +56,7 @@ pub enum Expr {
|
|||||||
args: Vec<Expr>,
|
args: Vec<Expr>,
|
||||||
},
|
},
|
||||||
Assign {
|
Assign {
|
||||||
val: Box<Expr>, //TODO this probably can't be a val
|
val: Box<Expr>,
|
||||||
expr: Box<Expr>,
|
expr: Box<Expr>,
|
||||||
},
|
},
|
||||||
Conditional {
|
Conditional {
|
||||||
@@ -164,7 +164,23 @@ impl<'a> Reducer<'a> {
|
|||||||
BoolLiteral(b) => Expr::Lit(Lit::Bool(*b)),
|
BoolLiteral(b) => Expr::Lit(Lit::Bool(*b)),
|
||||||
BinExp(binop, lhs, rhs) => self.binop(binop, lhs, rhs),
|
BinExp(binop, lhs, rhs) => self.binop(binop, lhs, rhs),
|
||||||
PrefixExp(op, arg) => self.prefix(op, arg),
|
PrefixExp(op, arg) => self.prefix(op, arg),
|
||||||
Value(qualified_name) => self.value(qualified_name),
|
Value(qualified_name) => {
|
||||||
|
let ref id = qualified_name.id;
|
||||||
|
let ref fqsn = match symbol_table.get_fqsn_from_id(id) {
|
||||||
|
Some(fqsn) => fqsn,
|
||||||
|
None => return Expr::ReductionError(format!("FQSN lookup for Value {:?} failed", qualified_name)),
|
||||||
|
};
|
||||||
|
//TODO this probably needs to change
|
||||||
|
match symbol_table.lookup_by_fqsn(&fqsn) {
|
||||||
|
Some(Symbol { spec: SymbolSpec::DataConstructor { index, type_args, type_name}, local_name, .. }) => Expr::Constructor {
|
||||||
|
type_name: type_name.clone(),
|
||||||
|
name: local_name.clone(),
|
||||||
|
tag: index.clone(),
|
||||||
|
arity: type_args.len(),
|
||||||
|
},
|
||||||
|
_ => Expr::Sym(fqsn.clone()),
|
||||||
|
}
|
||||||
|
},
|
||||||
Call { f, arguments } => self.reduce_call_expression(f, arguments),
|
Call { f, arguments } => self.reduce_call_expression(f, arguments),
|
||||||
TupleLiteral(exprs) => Expr::Tuple(exprs.iter().map(|e| self.expression(e)).collect()),
|
TupleLiteral(exprs) => Expr::Tuple(exprs.iter().map(|e| self.expression(e)).collect()),
|
||||||
IfExpression { discriminator, body } => self.reduce_if_expression(deref_optional_box(discriminator), body),
|
IfExpression { discriminator, body } => self.reduce_if_expression(deref_optional_box(discriminator), body),
|
||||||
@@ -177,38 +193,6 @@ impl<'a> Reducer<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn value(&mut self, qualified_name: &QualifiedName) -> Expr {
|
|
||||||
let symbol_table = self.symbol_table;
|
|
||||||
let ref id = qualified_name.id;
|
|
||||||
let ref sym_name = match symbol_table.get_fqsn_from_id(id) {
|
|
||||||
Some(fqsn) => fqsn,
|
|
||||||
None => return Expr::ReductionError(format!("FQSN lookup for Value {:?} failed", qualified_name)),
|
|
||||||
};
|
|
||||||
|
|
||||||
//TODO this probably needs to change
|
|
||||||
let FullyQualifiedSymbolName(ref v) = sym_name;
|
|
||||||
let name = v.last().unwrap().name.clone();
|
|
||||||
|
|
||||||
let Symbol { local_name, spec, .. } = match symbol_table.lookup_by_fqsn(&sym_name) {
|
|
||||||
Some(s) => s,
|
|
||||||
//None => return Expr::ReductionError(format!("Symbol {:?} not found", sym_name)),
|
|
||||||
None => return Expr::Sym(name.clone())
|
|
||||||
};
|
|
||||||
|
|
||||||
match spec {
|
|
||||||
SymbolSpec::RecordConstructor { .. } => Expr::ReductionError(format!("AST reducer doesn't expect a RecordConstructor here")),
|
|
||||||
SymbolSpec::DataConstructor { index, type_args, type_name } => Expr::Constructor {
|
|
||||||
type_name: type_name.clone(),
|
|
||||||
name: name.clone(),
|
|
||||||
tag: index.clone(),
|
|
||||||
arity: type_args.len(),
|
|
||||||
},
|
|
||||||
SymbolSpec::Func(_) => Expr::Sym(local_name.clone()),
|
|
||||||
SymbolSpec::Binding => Expr::Sym(local_name.clone()), //TODO not sure if this is right, probably needs to eventually be fqsn
|
|
||||||
SymbolSpec::Type { .. } => Expr::ReductionError("AST reducer doesnt expect a type here".to_string())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn reduce_lambda(&mut self, params: &Vec<FormalParam>, body: &Block) -> Expr {
|
fn reduce_lambda(&mut self, params: &Vec<FormalParam>, body: &Block) -> Expr {
|
||||||
Expr::Func(Func::UserDefined {
|
Expr::Func(Func::UserDefined {
|
||||||
name: None,
|
name: None,
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ impl Schala {
|
|||||||
symbol_table: symbols.clone(),
|
symbol_table: symbols.clone(),
|
||||||
source_map: source_map.clone(),
|
source_map: source_map.clone(),
|
||||||
resolver: crate::scope_resolution::ScopeResolver::new(symbols.clone()),
|
resolver: crate::scope_resolution::ScopeResolver::new(symbols.clone()),
|
||||||
state: eval::State::new(),
|
state: eval::State::new(symbols),
|
||||||
type_context: typechecking::TypeContext::new(),
|
type_context: typechecking::TypeContext::new(),
|
||||||
active_parser: parsing::Parser::new(source_map)
|
active_parser: parsing::Parser::new(source_map)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ pub struct ScopeResolver<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ASTVisitor for ScopeResolver<'a> {
|
impl<'a> ASTVisitor for ScopeResolver<'a> {
|
||||||
//TODO need to un-insert these - maybe need to rethink visitor
|
|
||||||
fn import(&mut self, import_spec: &ImportSpecifier) {
|
fn import(&mut self, import_spec: &ImportSpecifier) {
|
||||||
let ref symbol_table = self.symbol_table_handle.borrow();
|
let ref symbol_table = self.symbol_table_handle.borrow();
|
||||||
let ImportSpecifier { ref path_components, ref imported_names, .. } = &import_spec;
|
let ImportSpecifier { ref path_components, ref imported_names, .. } = &import_spec;
|
||||||
|
|||||||
@@ -21,10 +21,7 @@ pub enum TokenKind {
|
|||||||
|
|
||||||
Operator(Rc<String>),
|
Operator(Rc<String>),
|
||||||
DigitGroup(Rc<String>), HexLiteral(Rc<String>), BinNumberSigil,
|
DigitGroup(Rc<String>), HexLiteral(Rc<String>), BinNumberSigil,
|
||||||
StrLiteral {
|
StrLiteral(Rc<String>),
|
||||||
s: Rc<String>,
|
|
||||||
prefix: Option<Rc<String>>
|
|
||||||
},
|
|
||||||
Identifier(Rc<String>),
|
Identifier(Rc<String>),
|
||||||
Keyword(Kw),
|
Keyword(Kw),
|
||||||
|
|
||||||
@@ -40,7 +37,7 @@ impl fmt::Display for TokenKind {
|
|||||||
&Operator(ref s) => write!(f, "Operator({})", **s),
|
&Operator(ref s) => write!(f, "Operator({})", **s),
|
||||||
&DigitGroup(ref s) => write!(f, "DigitGroup({})", s),
|
&DigitGroup(ref s) => write!(f, "DigitGroup({})", s),
|
||||||
&HexLiteral(ref s) => write!(f, "HexLiteral({})", s),
|
&HexLiteral(ref s) => write!(f, "HexLiteral({})", s),
|
||||||
&StrLiteral {ref s, .. } => write!(f, "StrLiteral({})", s),
|
&StrLiteral(ref s) => write!(f, "StrLiteral({})", s),
|
||||||
&Identifier(ref s) => write!(f, "Identifier({})", s),
|
&Identifier(ref s) => write!(f, "Identifier({})", s),
|
||||||
&Error(ref s) => write!(f, "Error({})", s),
|
&Error(ref s) => write!(f, "Error({})", s),
|
||||||
other => write!(f, "{:?}", other),
|
other => write!(f, "{:?}", other),
|
||||||
@@ -166,7 +163,7 @@ pub fn tokenize(input: &str) -> Vec<Token> {
|
|||||||
'(' => LParen, ')' => RParen,
|
'(' => LParen, ')' => RParen,
|
||||||
'{' => LCurlyBrace, '}' => RCurlyBrace,
|
'{' => LCurlyBrace, '}' => RCurlyBrace,
|
||||||
'[' => LSquareBracket, ']' => RSquareBracket,
|
'[' => LSquareBracket, ']' => RSquareBracket,
|
||||||
'"' => handle_quote(&mut input, None),
|
'"' => handle_quote(&mut input),
|
||||||
'\\' => Backslash,
|
'\\' => Backslash,
|
||||||
c if c.is_digit(10) => handle_digit(c, &mut input),
|
c if c.is_digit(10) => handle_digit(c, &mut input),
|
||||||
c if c.is_alphabetic() || c == '_' => handle_alphabetic(c, &mut input),
|
c if c.is_alphabetic() || c == '_' => handle_alphabetic(c, &mut input),
|
||||||
@@ -194,7 +191,7 @@ fn handle_digit(c: char, input: &mut Peekable<impl Iterator<Item=CharData>>) ->
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_quote(input: &mut Peekable<impl Iterator<Item=CharData>>, quote_prefix: Option<&str>) -> TokenKind {
|
fn handle_quote(input: &mut Peekable<impl Iterator<Item=CharData>>) -> TokenKind {
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
loop {
|
loop {
|
||||||
match input.next().map(|(_, _, c)| { c }) {
|
match input.next().map(|(_, _, c)| { c }) {
|
||||||
@@ -216,7 +213,7 @@ fn handle_quote(input: &mut Peekable<impl Iterator<Item=CharData>>, quote_prefix
|
|||||||
None => return TokenKind::Error(format!("Unclosed string")),
|
None => return TokenKind::Error(format!("Unclosed string")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TokenKind::StrLiteral { s: Rc::new(buf), prefix: quote_prefix.map(|s| Rc::new(s.to_string())) }
|
TokenKind::StrLiteral(Rc::new(buf))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_alphabetic(c: char, input: &mut Peekable<impl Iterator<Item=CharData>>) -> TokenKind {
|
fn handle_alphabetic(c: char, input: &mut Peekable<impl Iterator<Item=CharData>>) -> TokenKind {
|
||||||
@@ -228,10 +225,6 @@ fn handle_alphabetic(c: char, input: &mut Peekable<impl Iterator<Item=CharData>>
|
|||||||
|
|
||||||
loop {
|
loop {
|
||||||
match input.peek().map(|&(_, _, c)| { c }) {
|
match input.peek().map(|&(_, _, c)| { c }) {
|
||||||
Some(c) if c == '"' => {
|
|
||||||
input.next();
|
|
||||||
return handle_quote(input, Some(&buf));
|
|
||||||
},
|
|
||||||
Some(c) if c.is_alphanumeric() || c == '_' => {
|
Some(c) if c.is_alphanumeric() || c == '_' => {
|
||||||
input.next();
|
input.next();
|
||||||
buf.push(c);
|
buf.push(c);
|
||||||
@@ -332,13 +325,4 @@ mod schala_tokenizer_tests {
|
|||||||
let token_kinds: Vec<TokenKind> = tokenize("1 `plus` 2").into_iter().map(move |t| t.kind).collect();
|
let token_kinds: Vec<TokenKind> = tokenize("1 `plus` 2").into_iter().map(move |t| t.kind).collect();
|
||||||
assert_eq!(token_kinds, vec![digit!("1"), op!("plus"), digit!("2")]);
|
assert_eq!(token_kinds, vec![digit!("1"), op!("plus"), digit!("2")]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn string_literals() {
|
|
||||||
let token_kinds: Vec<TokenKind> = tokenize(r#""some string""#).into_iter().map(move |t| t.kind).collect();
|
|
||||||
assert_eq!(token_kinds, vec![StrLiteral { s: Rc::new("some string".to_string()), prefix: None }]);
|
|
||||||
|
|
||||||
let token_kinds: Vec<TokenKind> = tokenize(r#"b"some bytestring""#).into_iter().map(move |t| t.kind).collect();
|
|
||||||
assert_eq!(token_kinds, vec![StrLiteral { s: Rc::new("some bytestring".to_string()), prefix: Some(Rc::new("b".to_string())) }]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user