Skip to content

Commit

Permalink
lang: implement very basic optional semicolon scheme
Browse files Browse the repository at this point in the history
The intention is to establish a baseline against which
more elaborate implementations can be compared.
  • Loading branch information
soc committed Jun 14, 2024
1 parent 9bfa54e commit c5c3cb5
Show file tree
Hide file tree
Showing 36 changed files with 1,977 additions and 2,060 deletions.
2 changes: 1 addition & 1 deletion bench/binarytrees/binarytrees-mt.dora
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ impl TreeThread {
fun run(): Unit {
while true {
let depth = self.nextDepth.fetchAdd(2i32);
if depth > self.maxDepth { return; }
if depth > self.maxDepth { return }
let result = loops(self.maxDepth, depth);
self.results((depth - MIN_DEPTH).toInt64() / 2i64) = result;
}
Expand Down
2 changes: 1 addition & 1 deletion bench/gcbench/gcbench.dora
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ fun numIters(i: Int32): Int32 {
fun populate(depth: Int32, thisNode: Node): Unit {
var depth = depth;
if depth <= 0i32 {
return;
return
} else {
depth = depth - 1i32;
thisNode.left = Option[Node]::Some(Node::leaf());
Expand Down
13 changes: 3 additions & 10 deletions bench/splay/splay.dora
Original file line number Diff line number Diff line change
Expand Up @@ -131,13 +131,6 @@ impl Benchmark {
fun generateKey(): Int32 {
return rnd.nextInt32();
}

fun rms(): Unit {
let pauses = self.splaySumOfSquaredPauses;
let samples = self.splaySamples;

(pauses.toFloat64() / samples.toFloat64());
}
}

fun generatePayloadTree(depth: Int32, tag: String): PayloadNode =
Expand Down Expand Up @@ -176,15 +169,15 @@ impl SplayTree {
fun insert(key: Int32, value: PayloadNode): Unit {
if self.isEmpty() {
self.root = Some(SplayNode::new(key, Some[PayloadNode](value)));
return;
return
}

self.splay(key);

let root = self.root.getOrPanic();

if root.key == key {
return;
return
}

let node = SplayNode::new(key, Some[PayloadNode](value));
Expand Down Expand Up @@ -287,7 +280,7 @@ impl SplayTree {

fun splay(key: Int32): Unit {
if self.isEmpty() {
return;
return
}

var dummy = SplayNode::new(0i32, Option[PayloadNode]::None);
Expand Down
8 changes: 0 additions & 8 deletions dora-parser/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1764,14 +1764,6 @@ impl Expr {
}
}

pub fn needs_semicolon(&self) -> bool {
match self {
&Expr::Block(_) => false,
&Expr::If(_) => false,
_ => true,
}
}

pub fn pos(&self) -> Position {
match *self {
Expr::Un(ref val) => val.pos,
Expand Down
2 changes: 1 addition & 1 deletion dora-parser/src/lexer/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ pub enum FloatSuffix {
Float64,
}

#[derive(Debug)]
#[derive(Clone, Debug)]
pub struct Token {
pub kind: TokenKind,
pub position: Position,
Expand Down
104 changes: 44 additions & 60 deletions dora-parser/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ impl<'a> Parser<'a> {
fn parse_use(&mut self) -> Result<Use, ParseErrorAndPos> {
self.expect_token(TokenKind::Use)?;
let use_declaration = self.parse_use_inner()?;
self.expect_semicolon()?;
self.skip_semicolon()?;

Ok(use_declaration)
}
Expand Down Expand Up @@ -325,7 +325,7 @@ impl<'a> Parser<'a> {
self.expect_token(TokenKind::RBrace)?;
Some(elements)
} else {
self.expect_token(TokenKind::Semicolon)?;
self.skip_semicolon()?;
None
};

Expand Down Expand Up @@ -372,7 +372,7 @@ impl<'a> Parser<'a> {
let ty = self.parse_type()?;
self.expect_token(TokenKind::Eq)?;
let expr = self.parse_expression()?;
self.expect_semicolon()?;
self.skip_semicolon()?;
let span = self.span_from(start);

Ok(Const {
Expand Down Expand Up @@ -447,7 +447,7 @@ impl<'a> Parser<'a> {
None
};

self.expect_semicolon()?;
self.skip_semicolon()?;
let span = self.span_from(start);

let mut global = Global {
Expand Down Expand Up @@ -976,22 +976,22 @@ impl<'a> Parser<'a> {
}

fn parse_function_block(&mut self) -> Result<Option<Box<ExprBlockType>>, ParseErrorAndPos> {
if self.token.is(TokenKind::Semicolon) {
self.advance_token()?;

Ok(None)
} else if self.token.is(TokenKind::Eq) {
if self.token.is(TokenKind::Eq) {
let expr = self.parse_function_block_expression()?;

Ok(Some(expr))
} else {
} else if self.token.is(TokenKind::LBrace) {
let block = self.parse_block()?;

if let Expr::Block(block_type) = *block {
Ok(Some(Box::new(block_type)))
} else {
unreachable!()
}
} else {
self.skip_semicolon()?;

Ok(None)
}
}

Expand All @@ -1012,7 +1012,7 @@ impl<'a> Parser<'a> {

_ => {
let expr = self.parse_expression()?;
self.expect_token(TokenKind::Semicolon)?;
self.skip_semicolon()?;
Ok(Box::new(ExprBlockType {
id: self.generate_id(),
pos: expr.pos(),
Expand Down Expand Up @@ -1124,18 +1124,12 @@ impl<'a> Parser<'a> {

match stmt_or_expr {
StmtOrExpr::Stmt(stmt) => Ok(stmt),
StmtOrExpr::Expr(expr) => {
if expr.needs_semicolon() {
Err(self.expect_semicolon().unwrap_err())
} else {
Ok(Box::new(Stmt::create_expr(
self.generate_id(),
expr.pos(),
expr.span(),
expr,
)))
}
}
StmtOrExpr::Expr(expr) => Ok(Box::new(Stmt::create_expr(
self.generate_id(),
expr.pos(),
expr.span(),
expr,
))),
}
}

Expand All @@ -1154,7 +1148,7 @@ impl<'a> Parser<'a> {
let data_type = self.parse_var_type()?;
let expr = self.parse_var_assignment()?;

self.expect_semicolon()?;
self.skip_semicolon()?;
let span = self.span_from(start);

Ok(Box::new(Stmt::create_let(
Expand Down Expand Up @@ -1254,10 +1248,7 @@ impl<'a> Parser<'a> {
match stmt_or_expr {
StmtOrExpr::Stmt(stmt) => stmts.push(stmt),
StmtOrExpr::Expr(curr_expr) => {
if curr_expr.needs_semicolon() {
expr = Some(curr_expr);
break;
} else if !self.token.is(TokenKind::RBrace) {
if !self.token.is(TokenKind::RBrace) {
stmts.push(Box::new(Stmt::create_expr(
self.generate_id(),
curr_expr.pos(),
Expand Down Expand Up @@ -1295,20 +1286,8 @@ impl<'a> Parser<'a> {
TokenKind::For => Ok(StmtOrExpr::Stmt(self.parse_for()?)),
_ => {
let expr = self.parse_expression()?;

if self.token.is(TokenKind::Semicolon) {
self.expect_token(TokenKind::Semicolon)?;
let span = self.span_from(expr.span().start());

Ok(StmtOrExpr::Stmt(Box::new(Stmt::create_expr(
self.generate_id(),
expr.pos(),
span,
expr,
))))
} else {
Ok(StmtOrExpr::Expr(expr))
}
self.skip_semicolon()?;
Ok(StmtOrExpr::Expr(expr))
}
}
}
Expand Down Expand Up @@ -1522,14 +1501,12 @@ impl<'a> Parser<'a> {
fn parse_return(&mut self) -> StmtResult {
let start = self.token.span.start();
let pos = self.expect_token(TokenKind::Return)?.position;
let expr = if self.token.is(TokenKind::Semicolon) {
None
} else {
let expr = self.parse_expression()?;
Some(expr)
let expr = match self.token.kind {
TokenKind::Semicolon | TokenKind::RBrace => None,
_ => Some(self.parse_expression()?),
};

self.expect_semicolon()?;
self.skip_semicolon()?;
let span = self.span_from(start);

Ok(Box::new(Stmt::create_return(
Expand Down Expand Up @@ -2107,6 +2084,18 @@ impl<'a> Parser<'a> {
self.expect_token(TokenKind::Semicolon)
}

fn skip_semicolon(&mut self) -> Result<Token, ParseErrorAndPos> {
if self.token.is(TokenKind::Semicolon)
/* || self.token.is(TokenKind::NewLine)*/
{
//println!("FOUND semi or nl: {:?}, advancing", self.token);
self.advance_token()
} else {
//println!("NOT found semi or nl: {:?}", self.token);
Ok(self.token.clone())
}
}

fn expect_token(&mut self, kind: TokenKind) -> Result<Token, ParseErrorAndPos> {
if self.token.kind == kind {
let token = self.advance_token()?;
Expand Down Expand Up @@ -2853,12 +2842,10 @@ mod tests {

#[test]
fn parse_expr_stmt_without_semicolon() {
err_stmt(
"1",
ParseError::ExpectedToken(";".into(), "<<EOF>>".into()),
1,
2,
);
let stmt = parse_stmt("1");
let expr = stmt.to_expr().unwrap();

assert!(expr.expr.is_lit_int());
}

#[test]
Expand Down Expand Up @@ -2914,15 +2901,12 @@ mod tests {
let (expr, _) = parse_expr("{ 1; 2; }");
let block = expr.to_block().unwrap();

assert_eq!(2, block.stmts.len());
assert_eq!(1, block.stmts.len());

let expr = &block.stmts[0].to_expr().unwrap().expr;
assert_eq!(1, expr.to_lit_int().unwrap().value);

let expr = &block.stmts[1].to_expr().unwrap().expr;
assert_eq!(2, expr.to_lit_int().unwrap().value);

assert!(block.expr.is_none());
assert!(block.expr.as_ref().unwrap().is_lit_int());
}

#[test]
Expand Down Expand Up @@ -3685,7 +3669,7 @@ mod tests {
fn parse_use_declaration() {
parse_err(
"use foo.bar{a, b, c}",
ParseError::ExpectedToken(";".into(), "{".into()),
ParseError::ExpectedTopLevelElement("{".into()),
1,
12,
);
Expand Down
Loading

0 comments on commit c5c3cb5

Please sign in to comment.