while loops
This commit is contained in:
13
README.md
13
README.md
@@ -211,7 +211,8 @@ User {
|
|||||||
|
|
||||||
### Control Flow
|
### Control Flow
|
||||||
|
|
||||||
Control flow in One is still quite limited, as the `for` keyword has not been implemented yet. `if`, `else` and `elif` statements are fully implemented and are written like this.
|
Control flow in One isn't fully implemented yet, but it is already functional.
|
||||||
|
`if`, `else` and `elif` statements are fully implemented and are written like this:
|
||||||
|
|
||||||
```
|
```
|
||||||
let x int = 17;
|
let x int = 17;
|
||||||
@@ -225,7 +226,15 @@ if x >= 100 {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Using parentheses around the condition isn't necessary.
|
`while` loops are very similar, and can be written like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
let i int = 0;
|
||||||
|
while i < 10 {
|
||||||
|
print(i);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### The main function
|
### The main function
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
module main
|
module main
|
||||||
|
|
||||||
import strings
|
import strings
|
||||||
@@ -158,6 +159,12 @@ fn (mut g Generator) gen_stmt(stmt Stmt) {
|
|||||||
g.out.write_string(') ')
|
g.out.write_string(') ')
|
||||||
g.gen_stmt(stmt.block)
|
g.gen_stmt(stmt.block)
|
||||||
}
|
}
|
||||||
|
WhileLoop {
|
||||||
|
g.out.write_string('while (')
|
||||||
|
g.gen_expr(stmt.guard)
|
||||||
|
g.out.write_string(') ')
|
||||||
|
g.gen_stmt(stmt.block)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
6
lexer.v
6
lexer.v
@@ -10,7 +10,7 @@ enum TokenType as u8 {
|
|||||||
kw_if
|
kw_if
|
||||||
kw_else
|
kw_else
|
||||||
kw_elif
|
kw_elif
|
||||||
kw_for
|
kw_while
|
||||||
kw_break
|
kw_break
|
||||||
kw_fn
|
kw_fn
|
||||||
kw_return
|
kw_return
|
||||||
@@ -106,7 +106,7 @@ fn toktype_from_kw(kw string) TokenType {
|
|||||||
'if' {.kw_if}
|
'if' {.kw_if}
|
||||||
'else' {.kw_else}
|
'else' {.kw_else}
|
||||||
'elif' {.kw_elif}
|
'elif' {.kw_elif}
|
||||||
'for' {.kw_for}
|
'while' {.kw_while}
|
||||||
'break' {.kw_break}
|
'break' {.kw_break}
|
||||||
'fn' {.kw_fn}
|
'fn' {.kw_fn}
|
||||||
'return' {.kw_return}
|
'return' {.kw_return}
|
||||||
@@ -133,7 +133,7 @@ fn is_real(str string) bool {
|
|||||||
|
|
||||||
fn is_keyword(str string) bool {
|
fn is_keyword(str string) bool {
|
||||||
return [
|
return [
|
||||||
"void", "int", "real", "bool", "string", "if", "else", "elif", "for", "break", "fn", "return", "let", "const", "true", "false", "print", "class", "immutable"
|
"void", "int", "real", "bool", "string", "if", "else", "elif", "while", "break", "fn", "return", "let", "const", "true", "false", "print", "class", "immutable"
|
||||||
].contains(str)
|
].contains(str)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
28
parser.v
28
parser.v
@@ -122,7 +122,9 @@ fn (mut s SymbolTable) is_in_global_scope() bool {
|
|||||||
|
|
||||||
// ------------------------------------------- Expressions
|
// ------------------------------------------- Expressions
|
||||||
|
|
||||||
type Expr = VoidExpr | UnaryExpr | BinaryExpr | IntegerLiteral | RealLiteral | BoolLiteral | StringLiteral | Variable | TypeExpr | Function | TypeCast | ParenExpr | PrintExpr | FnCall | ClassMember | ClassInstantiation | MemberAccess
|
type Expr = VoidExpr | UnaryExpr | BinaryExpr | IntegerLiteral | RealLiteral | BoolLiteral | StringLiteral |
|
||||||
|
Variable | TypeExpr | Function | TypeCast | ParenExpr | PrintExpr | FnCall | ClassMember |
|
||||||
|
ClassInstantiation | MemberAccess
|
||||||
|
|
||||||
struct VoidExpr {}
|
struct VoidExpr {}
|
||||||
|
|
||||||
@@ -204,7 +206,8 @@ struct FnCall {
|
|||||||
|
|
||||||
// ------------------------------------------- Statements
|
// ------------------------------------------- Statements
|
||||||
|
|
||||||
type Stmt = VarDecl | ExprStmt | ReturnStmt | Block | IfStmt | ElseStmt | ElifStmt | FuncDecl | Param | ClassDecl
|
type Stmt = VarDecl | ExprStmt | ReturnStmt | Block | IfStmt | ElseStmt | ElifStmt | FuncDecl | Param |
|
||||||
|
ClassDecl | WhileLoop
|
||||||
|
|
||||||
struct VarDecl {
|
struct VarDecl {
|
||||||
name string
|
name string
|
||||||
@@ -251,6 +254,11 @@ struct ElifStmt {
|
|||||||
block Block
|
block Block
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct WhileLoop {
|
||||||
|
guard Expr
|
||||||
|
block Block
|
||||||
|
}
|
||||||
|
|
||||||
struct Param {
|
struct Param {
|
||||||
name string
|
name string
|
||||||
type string
|
type string
|
||||||
@@ -529,6 +537,10 @@ fn (mut p Parser) get_expr_is_immutable(expr Expr) bool {
|
|||||||
memberinfo := classinfo.members_info[expr.member] or {parse_error("Undefined member ${expr.member}")}
|
memberinfo := classinfo.members_info[expr.member] or {parse_error("Undefined member ${expr.member}")}
|
||||||
memberinfo.is_immutable
|
memberinfo.is_immutable
|
||||||
}
|
}
|
||||||
|
Variable {
|
||||||
|
varinfo := p.symbols.lookup_var(expr.name) or {parse_error("Undefined variable ${expr.name}")}
|
||||||
|
varinfo.is_immutable
|
||||||
|
}
|
||||||
else {true}
|
else {true}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -616,6 +628,7 @@ fn (mut p Parser) parse_statement() Stmt {
|
|||||||
.kw_if {return p.parse_if()}
|
.kw_if {return p.parse_if()}
|
||||||
.kw_else {return p.parse_else()}
|
.kw_else {return p.parse_else()}
|
||||||
.kw_elif {return p.parse_elif()}
|
.kw_elif {return p.parse_elif()}
|
||||||
|
.kw_while {return p.parse_while()}
|
||||||
else {return p.parse_expr_stmt()}
|
else {return p.parse_expr_stmt()}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -768,6 +781,17 @@ fn (mut p Parser) parse_return_stmt() ReturnStmt {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (mut p Parser) parse_while() WhileLoop {
|
||||||
|
p.expect(.kw_while)
|
||||||
|
cond := p.parse_expr(.base)
|
||||||
|
if p.get_expr_type(cond) != 'bool' {
|
||||||
|
parse_error('While loop guard must be of type bool')
|
||||||
|
}
|
||||||
|
block := p.parse_block(false)
|
||||||
|
|
||||||
|
return WhileLoop {cond, block}
|
||||||
|
}
|
||||||
|
|
||||||
fn (mut p Parser) parse_if() IfStmt {
|
fn (mut p Parser) parse_if() IfStmt {
|
||||||
p.expect(.kw_if)
|
p.expect(.kw_if)
|
||||||
cond := p.parse_expr(.base)
|
cond := p.parse_expr(.base)
|
||||||
|
|||||||
Reference in New Issue
Block a user