summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJJ2023-04-06 21:24:38 +0000
committerJJ2023-04-06 21:24:38 +0000
commit95ce33948581a10c2d55793b6317c7ce273f936a (patch)
tree410383a56b51af9644fa309bbe3f03d9d2368bb6 /src
parent3188a0ec2174945a6b004db78b534f80c7927796 (diff)
rename project, write parser tests
Diffstat (limited to 'src')
-rw-r--r--src/ast.rs11
-rw-r--r--src/lib.rs6
-rw-r--r--src/main.rs12
-rw-r--r--src/parser.rs35
-rw-r--r--src/simple.rs17
-rw-r--r--src/util.rs60
6 files changed, 100 insertions, 41 deletions
diff --git a/src/ast.rs b/src/ast.rs
index 9202968..4bbc7ed 100644
--- a/src/ast.rs
+++ b/src/ast.rs
@@ -19,7 +19,7 @@ pub enum Expression {
// _every_ type in our language is represented as this and interpreted as a type.
// how to store more data than fits... hmm
-pub type Value = i8;
+pub type Value = u64;
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Type {
@@ -27,6 +27,7 @@ pub enum Type {
Unit,
Bool,
Natural,
+ Integer,
// Float,
// String,
// Enum(Vec<Type>),
@@ -44,12 +45,12 @@ pub struct Term {
impl fmt::Debug for Expression {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
- Expression::Annotation { expr, kind } => write!(f, "{:?}:{:?}", expr, kind),
- Expression::Constant { term } => write!(f, "{}", term.val),
+ Expression::Annotation { expr, kind } => write!(f, "({:?}: {:?})", expr, kind),
+ Expression::Constant { term } => write!(f, "'{}", term.val),
Expression::Variable { id } => write!(f, "{}", id),
Expression::Abstraction { param, func } => write!(f, "(λ{}.{:?})", param, func),
- Expression::Application { func, arg } => write!(f, "{:?} {:?}", func, arg),
- Expression::Conditional { if_cond, if_then, if_else } => write!(f, "if {:?} then {:?} else {:?}", if_cond, if_then, if_else),
+ Expression::Application { func, arg } => write!(f, "({:?} {:?})", func, arg),
+ Expression::Conditional { if_cond, if_then, if_else } => write!(f, "(if {:?} then {:?} else {:?})", if_cond, if_then, if_else),
}
}
}
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..f4a5765
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,6 @@
+pub mod ast;
+// pub mod classes;
+// pub mod effects;
+pub mod parser;
+pub mod util;
+pub mod simple;
diff --git a/src/main.rs b/src/main.rs
index f31e163..6d74f54 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,14 +1,10 @@
use std::io::{Write, stdout, stdin};
-use crate::ast::*;
-mod ast;
-mod classes;
-mod effects;
-mod parser;
-mod simple;
+use chrysanthemum::*;
+use chrysanthemum::ast::*;
fn main() {
- println!("type-systems");
+ println!("chrysanthemum");
let mut input = String::new();
loop {
println!("infer, check, or execute? (i/c/e)");
@@ -43,7 +39,7 @@ fn main() {
input.clear();
stdin().read_line(&mut input).unwrap();
- simple::execute(Context::new(), parser::parse(&input));
+ println!("{:?}", simple::execute(Context::new(), parser::parse(&input)));
},
_ => println!("invalid option {}. please try again.", input.trim())
}
diff --git a/src/parser.rs b/src/parser.rs
index cb86ea7..2f918a8 100644
--- a/src/parser.rs
+++ b/src/parser.rs
@@ -15,13 +15,29 @@ pub fn parse_str(input: &str) -> Result<Expression, peg::error::ParseError<peg::
= i:['a'..='z' | 'A'..='Z' | '0'..='9']+ {
i.iter().collect::<String>()
}
+ rule constant() -> Expression
+ = p:"-"? c:['0'..='9']+ {
+ let value = c.iter().collect::<String>().parse::<Value>().unwrap();
+ Expression::Constant {
+ term: Term {
+ val: if let Some(_) = p {
+ value.wrapping_neg()
+ } else {
+ value
+ },
+ kind: Type::Empty
+ }
+ }
+ }
rule kind() -> Type
= k:identifier() {
match k.as_str() {
+ "empty" => Type::Empty,
"unit" => Type::Unit,
"bool" => Type::Bool,
- "int" => Type::Natural,
- _ => panic!("invalid type")
+ "nat" => Type::Natural,
+ "int" => Type::Integer,
+ _ => panic!("invalid type"), // fixme: raise an error
}
}
rule annotation() -> Expression
@@ -31,31 +47,22 @@ pub fn parse_str(input: &str) -> Result<Expression, peg::error::ParseError<peg::
kind: k
}
}
- rule constant() -> Expression
- = c:['0'..='9']+ {
- Expression::Constant {
- term: Term {
- val: c.iter().collect::<String>().parse::<Value>().unwrap(),
- kind: Type::Empty
- }
- }
- }
rule variable() -> Expression
= v:identifier() {
Expression::Variable {
id: v
}
}
- // fixme: lambda is causing problems with rust-peg
rule abstraction() -> Expression
- = "λ" " "* p:identifier() " "+ "." " "+ f:expression() {
+ = ("λ" / "lambda ") " "* p:identifier() " "* "." " "* f:expression() {
Expression::Abstraction {
param: p,
func: Box::new(f)
}
}
+ // fixme: more cases should parse, but how?
rule application() -> Expression
- = "(" f:(abstraction() / annotation()) ")" " "+ a:expression() {
+ = "(" f:(annotation() / abstraction()) ")" " "* a:expression() {
Expression::Application {
func: Box::new(f),
arg: Box::new(a)
diff --git a/src/simple.rs b/src/simple.rs
index f71da46..9393c00 100644
--- a/src/simple.rs
+++ b/src/simple.rs
@@ -17,7 +17,7 @@ pub fn execute(context: Context, expression: Expression) -> Term {
Expression::Annotation { expr, .. } => return execute(context, *expr),
Expression::Constant { term } => return term,
Expression::Variable { id } => return context[&id],
- Expression::Abstraction { .. } => panic!(),
+ Expression::Abstraction { .. } => panic!("attempting to execute an abstraction"),
Expression::Application { func, arg } => {
match *func {
Expression::Abstraction { param, func } => {
@@ -25,26 +25,15 @@ pub fn execute(context: Context, expression: Expression) -> Term {
context.insert(param, execute(context.clone(), *arg));
return execute(context, *func);
},
- _ => panic!()
+ _ => panic!("attempting to execute an application to nothing")
}
},
Expression::Conditional { if_cond, if_then, if_else } => {
match execute(context.clone(), *if_cond).val {
1 => execute(context, *if_then),
0 => execute(context, *if_else),
- _ => panic!()
+ _ => panic!("invalid type for a conditional")
}
},
}
}
-
-// intentionally small: i want to run into errors
-/// assumption: the count is instantiated to zero
-fn uniquify(count: &mut u8) -> String {
- *count += 1;
- if *count == 0 {
- panic!("we've overflowed!");
- } else {
- return String::from(format!("{:X}", count));
- }
-}
diff --git a/src/util.rs b/src/util.rs
new file mode 100644
index 0000000..9ed38d1
--- /dev/null
+++ b/src/util.rs
@@ -0,0 +1,60 @@
+#![allow(non_snake_case)]
+
+use crate::ast::*;
+
+// intentionally small: i want to run into errors
+/// assumption: the count is instantiated to zero
+pub fn unique_ident(count: &mut u8) -> String {
+ *count += 1;
+ if *count == 0 {
+ panic!("we've overflowed!");
+ } else {
+ return String::from(format!("{:X}", count));
+ }
+}
+
+pub fn Term(val: Value, kind: Type) -> Term {
+ return Term {val, kind};
+}
+
+pub fn Ann(expr: Expression, kind: Type) -> Expression {
+ return Expression::Annotation {
+ expr: Box::new(expr),
+ kind: kind
+ };
+}
+
+pub fn Const(val: Value, kind: Type) -> Expression {
+ return Expression::Constant {
+ term: Term {val, kind}
+ };
+}
+
+pub fn Var(id: &str) -> Expression {
+ return Expression::Variable {
+ id: String::from(id)
+ };
+}
+
+pub fn Abs(param: &str, func: Expression) -> Expression {
+ return Expression::Abstraction {
+ param: String::from(param),
+ func: Box::new(func),
+ };
+}
+
+pub fn App(func: Expression, arg: Expression) -> Expression {
+ return Expression::Application {
+ func: Box::new(func),
+ arg: Box::new(arg)
+ };
+}
+
+pub fn Cond(if_cond: Expression, if_then: Expression, if_else: Expression) -> Expression {
+ return Expression::Conditional {
+ if_cond: Box::new(if_cond),
+ if_then: Box::new(if_then),
+ if_else: Box::new(if_else)
+ };
+}
+