-
Notifications
You must be signed in to change notification settings - Fork 1
Description
Should there be a distinction between statements and expressions? What should be an expression and what a statement? Is the top level to be composed of statements or expressions?
There is also a difference between separators and terminators. For example it is different whether val or def declarations are terminated by semicolons (the semicolon is part of their grammar rule) or like now, they are just statements separated by semicolons (just like any other statements are serparated by semicolons).
Should initial separator be allowed? E.g. the ML / Haskell style:
def fun
(
, aVeryLongArgumentNameThatOnlyFitsOnItsOwnLine
, aVeryLongArgumentNameThatOnlyFitsOnItsOwnLine2
)
= 1;
What should be the behaviour of these block expressions: {}, { f() }, { f(); }?
It seems to me that the syntax is already Scala like, and having "everything as expression" would maybe be simpler.
I originally wanted to submit a PR to allow initial separators and to somewhat solve the block expression. But I wasn't sure what you intended. My understanding of block expressions is:
{}= evaluates asNone{ f() }=evaluates tof()`{ f(); }=f()executed but result discarded, the block evaluates toNone
This corresponds to the idea that blocks contain expressions separated by semicolons, but trailing separator means implicit None. I don't know whether this is desirable for block expressions or the top level. The idea for implementation is below.
diff --git a/Cacom/src/ast.rs b/Cacom/src/ast.rs
index 5ab4da9..1870251 100644
--- a/Cacom/src/ast.rs
+++ b/Cacom/src/ast.rs
@@ -48,6 +48,12 @@ pub enum AST {
Expression(Expr),
}
+impl Default for AST {
+ fn default() -> Self {
+ Self::Expression(Expr::NoneVal)
+ }
+}
+
/// Expressions always leave some value on the stack
///
/// For example, if statement always leaves resulting value
diff --git a/Cacom/src/grammar.lalrpop b/Cacom/src/grammar.lalrpop
index b486327..46025c4 100644
--- a/Cacom/src/grammar.lalrpop
+++ b/Cacom/src/grammar.lalrpop
@@ -160,9 +160,8 @@ String: String = {
Block: Expr = {
CURLYBOPEN <Statements> CURLYBCLOSE => Expr::Block(<>),
- CURLYBOPEN CURLYBCLOSE => Expr::NoneVal,
}
-Statements = SeparatedLeastOne<Statement, SEMICOLON>;
+Statements = SeparatedLastMayDefault<Statement, SEMICOLON>;
FunDecl: AST = {
DEF <name: Identifier> LPAREN <parameters: Parameters> RPAREN ASSIGN <body: Expr> => {
@@ -184,7 +183,7 @@ Return: AST = {
// Macros
Separated<T, S>: Vec<T> = {
- <mut v: (<T> S)*> <e: T?> => match e {
+ <mut v: S? (<T> S)*> <e: T?> => match e {
None => v,
Some(e) => { v.push(e); v }
}
@@ -193,3 +192,14 @@ Separated<T, S>: Vec<T> = {
SeparatedLeastOne<T, S>: Vec<T> = {
<mut v: (<T> S)*> <e: T> S? => { v.push(e); v }
};
+
+SeparatedLastMayDefault<T, S>: Vec<T> = {
+ <mut v: (<T> S)*> <e: T?> => {
+ let e = match e {
+ Some(e) => e,
+ None => Default::default(),
+ };
+ v.push(e);
+ v
+ }
+};