Skip to content

Commit

Permalink
TMP
Browse files Browse the repository at this point in the history
  • Loading branch information
Cypher1 committed May 6, 2024
1 parent efc8905 commit 38cb2fe
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 33 deletions.
2 changes: 1 addition & 1 deletion examples/fib.tk
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env tako
// test: todo
// test: all

fib(n: T, {T: Nat}): T=if(n<=1, 1, fib(n-1)+fib(n-2))

Expand Down
2 changes: 1 addition & 1 deletion examples/fib_acc.tk
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env tako
// test: todo
// test: all

fib_helper(n: T, a: T, b: T, {T: Nat}): T=if(n==0, a, fib_helper(n-1, b, a+b))

Expand Down
2 changes: 1 addition & 1 deletion examples/generic_abstract_data_types.tk
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env tako
// test: todo
// test: all

// A simple, untyped implementation of S expressions.
SExpr: Type = struct.new(
Expand Down
2 changes: 1 addition & 1 deletion examples/instances.tk
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env tako
// test: todo parse error
// test: all

Bounded = Enum
.open()
Expand Down
2 changes: 1 addition & 1 deletion examples/vector_transpose.tk
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env tako
// test: todo parse
// test: all

main = {
x3by2 = Vector.new([
Expand Down
2 changes: 1 addition & 1 deletion examples/vector_transpose_failing.tk
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env tako
// test: todo type error fix parse error
// test: type error

main() = {
x3by2 = Vector.new([
Expand Down
69 changes: 43 additions & 26 deletions takolib/src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::ast::string_interner::Identifier;
use crate::ast::{Ast, Atom, Call, Contains, Definition, NodeData, NodeId, Op};
use crate::error::TError;
use better_std::include_strs;
use log::{debug, trace};
use log::trace;
use semantics::BindingMode;
use semantics::Literal;
use smallvec::smallvec;
Expand Down Expand Up @@ -476,42 +476,57 @@ impl<'src, 'toks, T: Iterator<Item = &'toks Token>> ParseState<'src, 'toks, T> {
let location = token.location();
trace!("Expr: {token:?} (binding {binding:?})");
let mut left = if self.operator_is(Symbol::OpenBracket).is_ok() {
// TODO: Support tuples.
// TODO: Support sequence&dictionary syntax.
// Tuple, parenthesized expr... etc.
let left = self.expr(Symbol::OpenParen)?;
self.require(TokenType::Op(Symbol::CloseBracket))?;
let mut left = self.expr(Symbol::OpenParen)?;
while self.operator_is(Symbol::CloseBracket).is_err() {
let op = if self.require(TokenType::Op(Symbol::Comma)).is_ok() {
Symbol::Comma
} else if self.require(TokenType::Op(Symbol::Sequence)).is_ok() {
Symbol::Sequence
} else if self.require(TokenType::Op(Symbol::CloseBracket)).is_ok() {
break;
} else {
Symbol::Comma
};

let right = self.expr(Symbol::OpenParen)?;
left = self.ast.add_op(
Op {
op,
args: smallvec![left, right],
},
location,
);
}
left
} else if self.operator_is(Symbol::OpenCurly).is_ok() {
// TODO: Support sequence&dictionary syntax.
// Tuple, parenthesized expr... etc.
let mut left = self.expr(Symbol::OpenParen)?;
let mut joiner = Symbol::Sequence;
while self.operator_is(Symbol::CloseCurly).is_err() {
// TODO: Clean up sequence generation.
// TODO: Check that a sequence / args is of the right structure?
let next = self.expr(Symbol::OpenParen)?;
let op = if self.require(TokenType::Op(Symbol::Comma)).is_ok() {
Symbol::Comma
} else if self.require(TokenType::Op(Symbol::Sequence)).is_ok() {
Symbol::Sequence
} else if self.require(TokenType::Op(Symbol::CloseCurly)).is_ok() {
break;
} else {
Symbol::Comma
};

let right = self.expr(Symbol::OpenParen)?;
left = self.ast.add_op(
Op {
op: joiner,
args: smallvec![left, next],
op,
args: smallvec![left, right],
},
location,
);
if self.require(TokenType::Op(Symbol::Comma)).is_ok() {
// TODO: Set next joiner
joiner = Symbol::Comma;
} else if self.require(TokenType::Op(Symbol::Sequence)).is_ok() {
// TODO: Set next joiner
joiner = Symbol::Sequence;
} else {
// Allow it? Maybe...
joiner = Symbol::Sequence;
}
}
left
} else if self.operator_is(Symbol::OpenParen).is_ok() {
// TODO: Support list syntax.
// Tuple, parenthesized expr... etc.
// Parenthesized expr... etc.
let left = self.expr(Symbol::OpenParen)?;
self.require(TokenType::Op(Symbol::CloseParen))?;
left
Expand All @@ -522,7 +537,12 @@ impl<'src, 'toks, T: Iterator<Item = &'toks Token>> ParseState<'src, 'toks, T> {
} else {
let _ = self.token();
match symbol.binding_type() {
OpBinding::Open => todo!("Should have already been handled"),
OpBinding::Open | OpBinding::Close => {
return Err(TError::InternalError {
message: format!("{symbol:?} should have already been handled"),
location: Some(location),
})
}
OpBinding::PrefixOp | OpBinding::PrefixOrInfixBinOp => {
let right = self.expr(binding)?;
self.ast.add_op(
Expand All @@ -534,9 +554,6 @@ impl<'src, 'toks, T: Iterator<Item = &'toks Token>> ParseState<'src, 'toks, T> {
)
}
_ => {
let st = location.start.into();
let end = std::cmp::min(st + 50, self.contents.len());
debug!("ERROR AT:\n{}", &self.contents[st..end]);
return Err(ParseError::MissingLeftHandSideOfOperator {
op: symbol,
location,
Expand Down
29 changes: 28 additions & 1 deletion takolib/src/test.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
// Integration tests
use log::info;
use log::{debug, info};
use std::fs;
use std::path::PathBuf;
use test_each;

use crate::error::TError;

const TEST_CONFIG_PREFIX: &str = "// test: ";

#[derive(Debug, Default, Eq, PartialEq, Ord, PartialOrd)]
Expand All @@ -13,6 +15,7 @@ enum TestResult {
TypeError,
ParseError,
LexError,
InternalError,
}

#[derive(Debug, Default, Eq, PartialEq, Ord, PartialOrd)]
Expand All @@ -31,6 +34,7 @@ impl TestConfig {
"type" => expect = TestResult::TypeError,
"lex" => expect = TestResult::LexError,
"parse" => expect = TestResult::ParseError,
"internal" => expect = TestResult::InternalError,
"all" => expect = TestResult::All,
_ => panic!("Unknown test tag {tag:?} in {ctx:#?}"),
}
Expand Down Expand Up @@ -86,6 +90,29 @@ fn parse_example_files(file: PathBuf) {

// TODO: Macro or helper?
let _ast = match crate::parser::parse(&file, &contents, &tokens) {
Err(TError::InternalError { message, location }) => {
let st = location.map(|l| l.start.into()).unwrap_or(0);
let end = std::cmp::min(st + 50, contents.len());
debug!("ERROR AT:\n{}", &contents[st..end]);
assert_eq!(
setting.expect,
TestResult::InternalError,
"Unexpected failure for: {file:?}\n{message:?}"
);
return;
}
Err(TError::ParseError(e)) => {
let location = e.location();
let st = location.map(|l| l.start.into()).unwrap_or(0);
let end = std::cmp::min(st + 50, contents.len());
debug!("ERROR AT:\n{}", &contents[st..end]);
assert_eq!(
setting.expect,
TestResult::ParseError,
"Unexpected failure for: {file:?}\n{e:?}"
);
return;
}
Err(e) => {
assert_eq!(
setting.expect,
Expand Down

0 comments on commit 38cb2fe

Please sign in to comment.