9 Commits

Author SHA1 Message Date
greg
9d24d48825 Add a few more things to an Expression-only visitor 2019-07-30 00:32:25 -07:00
greg
c3c515284d Super-simple visitor doing something 2019-07-29 20:15:34 -07:00
greg
0903277b69 simple expression 2019-07-29 19:44:46 -07:00
greg
94c4dec9a9 Notes 2019-07-28 20:11:19 -07:00
greg
42bc4f091c Rename visitor, add note 2019-07-28 20:11:19 -07:00
greg
be2dcb5301 Add initial visitor.rs 2019-07-28 20:11:19 -07:00
greg
88029fc55a Move bx macro to util 2019-07-28 20:11:19 -07:00
greg
37c77d93d7 Fix off-by-one error in show-immediate parsing 2019-07-28 11:26:13 -07:00
greg
b62968379a Replace matches with functional constructs 2019-07-28 11:15:28 -07:00
8 changed files with 76 additions and 27 deletions

View File

@@ -62,6 +62,7 @@ of learning how to write a programming language.
### General
http://thume.ca/2019/04/18/writing-a-compiler-in-rust/
http://thume.ca/2019/07/14/a-tour-of-metaprogramming-models-for-generics/
### Type-checking
https://skillsmatter.com/skillscasts/10868-inside-the-rust-compiler

3
VISITOR_NOTES Normal file
View File

@@ -0,0 +1,3 @@
-each terminal node in the AST requires a method on ASTVisitor
-this can maybe be done with a macro?

View File

@@ -4,7 +4,7 @@
#![feature(slice_patterns, box_patterns, box_syntax)]
//! `schala-lang` is where the Schala programming language is actually implemented.
//! It defines the `Schala` type, which contains the state for a Schala REPL, and implements
//! The crate defines the `Schala` type, which contains the state for a Schala REPL, and implements
//! `ProgrammingLanguageInterface` and the chain of compiler passes for it.
extern crate itertools;
@@ -17,16 +17,10 @@ extern crate schala_repl;
extern crate schala_lang_codegen;
extern crate ena;
macro_rules! bx {
($e:expr) => { Box::new($e) }
}
#[macro_use]
mod util;
#[macro_use]
mod typechecking;
mod tokenizing;
mod ast;
mod parsing;
@@ -34,7 +28,7 @@ mod symbol_table;
mod builtin;
mod reduced_ast;
mod eval;
mod schala;
mod visitor;
pub use schala::Schala;

View File

@@ -143,15 +143,11 @@
//!
mod test;
use std::rc::Rc;
use crate::tokenizing::*;
use crate::tokenizing::Kw::*;
use crate::tokenizing::TokenKind::*;
use crate::ast::*;
use crate::builtin::{BinOp, PrefixOp};
/// Represents a parsing error

View File

@@ -96,11 +96,7 @@ fn tokenizing(input: &str, _handle: &mut Schala, comp: Option<&mut PassDebugArti
fn parsing(input: Vec<tokenizing::Token>, handle: &mut Schala, comp: Option<&mut PassDebugArtifact>) -> Result<ast::AST, String> {
use crate::parsing::Parser;
let mut parser = match handle.active_parser.take() {
None => Parser::new(input),
Some(parser) => parser
};
let mut parser = handle.active_parser.take().unwrap_or_else(|| Parser::new(input));
let ast = parser.parse();
let trace = parser.format_parse_trace();
@@ -133,15 +129,13 @@ fn format_parse_error(error: parsing::ParseError, handle: &mut Schala) -> String
}
fn symbol_table(input: ast::AST, handle: &mut Schala, comp: Option<&mut PassDebugArtifact>) -> Result<ast::AST, String> {
let add = handle.symbol_table.borrow_mut().add_top_level_symbols(&input);
match add {
Ok(()) => {
handle.symbol_table.borrow_mut().add_top_level_symbols(&input).map(|()| {
comp.map(|comp| {
let debug = handle.symbol_table.borrow().debug_symbol_table();
comp.map(|comp| comp.add_artifact(debug));
Ok(input)
},
Err(msg) => Err(msg)
}
comp.add_artifact(debug);
});
input
})
}
fn typechecking(input: ast::AST, handle: &mut Schala, comp: Option<&mut PassDebugArtifact>) -> Result<ast::AST, String> {

View File

@@ -2,6 +2,10 @@ use std::collections::HashMap;
use std::hash::Hash;
use std::cmp::Eq;
macro_rules! bx {
($e:expr) => { Box::new($e) }
}
#[derive(Default, Debug)]
pub struct ScopeStack<'a, T: 'a, V: 'a> where T: Hash + Eq {
parent: Option<&'a ScopeStack<'a, T, V>>,

View File

@@ -0,0 +1,57 @@
use std::rc::Rc;
use crate::builtin::{BinOp, PrefixOp};
use crate::ast::{Expression, ExpressionKind, InvocationArgument, Meta};
pub trait ExpressionKindVisitor<T> {
fn nat_literal(&mut self, n: &u64) -> T;
fn float_literal(&mut self, f: &f64) -> T;
fn string_literal(&mut self, s: Rc<String>) -> T;
fn bool_literal(&mut self, b: &bool) -> T;
fn binexp(&mut self, op: &BinOp, lhs: &Expression, rhs: &Expression) -> T;
fn prefix_exp(&mut self, op: &PrefixOp, arg: &Expression) -> T;
fn value(&mut self, value_name: Rc<String>) -> T;
fn call_expression(&mut self, f: &Expression, arguments: &Vec<Meta<InvocationArgument>>) -> T;
}
pub fn dispatch<T>(input: &ExpressionKind, visitor: &mut dyn ExpressionKindVisitor<T>) -> T {
use ExpressionKind::*;
match input {
NatLiteral(n) => visitor.nat_literal(n),
FloatLiteral(f) => visitor.float_literal(f),
StringLiteral(s) => visitor.string_literal(s.clone()),
BoolLiteral(b) => visitor.bool_literal(b),
BinExp(op, box lhs, box rhs) => visitor.binexp(op, lhs.node(), rhs.node()),
PrefixExp(op, box arg) => visitor.prefix_exp(op, arg.node()),
Value(val_name) => visitor.value(val_name.clone()),
Call { box f, arguments } => visitor.call_expression(f.node(), arguments),
_ => panic!()
}
}
/*
struct NumberSummer;
impl ExpressionKindVisitor<u64> for NumberSummer {
fn nat_literal(&mut self, n: &u64) -> u64 { n.clone() }
fn float_literal(&mut self, f: &f64) -> u64
fn string_literal(&mut self, s: Rc<String>) -> u64 { 0 }
fn binexp(&mut self, op: &BinOp, lhs: &Expression, rhs: &Expression) -> u64 {
let lhs = dispatch(&lhs.kind, self);
let rhs = dispatch(&rhs.kind, self);
lhs + rhs
}
}
#[test]
fn yolo_swagg() {
use super::*;
let mut t = NumberSummer;
let x = ExpressionKind::NatLiteral(4);
let result = dispatch(&x, &mut t);
assert_eq!(result, 4);
}
*/

View File

@@ -48,14 +48,14 @@ impl DirectiveAction {
},
ShowImmediate => {
let cur_state = repl.get_cur_language_state();
let stage_name = match arguments.get(1) {
let stage_name = match arguments.get(0) {
Some(s) => s.to_string(),
None => return Some(format!("Must specify a thing to debug")),
};
let meta = LangMetaRequest::ImmediateDebug(DebugAsk::ByStage { stage_name: stage_name.clone(), token: None });
let meta_response = cur_state.request_meta(meta);
let response = match meta_response {
let response = match meta_response {
LangMetaResponse::ImmediateDebug(DebugResponse { ask, value }) => match ask {
DebugAsk::ByStage { stage_name: ref this_stage_name, ..} if *this_stage_name == stage_name => value,
_ => return Some(format!("Wrong debug stage"))