Refactor mutability

This commit is contained in:
mars 2022-03-01 10:27:41 -07:00
parent 9d074ddd19
commit 4fcad8c6a4
5 changed files with 38 additions and 37 deletions

View File

@ -15,7 +15,7 @@ pub enum Token {
#[token("else")] Else,
#[token("in")] In,
#[token("let")] Let,
#[token("var")] Var,
#[token("mut")] Mut,
#[token("interface")] Interface,
#[token("impl")] Impl,

View File

@ -30,7 +30,7 @@ impl ColorTheme {
pub fn token_style(&self, token: &Token) -> &Style {
use Token::*;
match token {
Struct | Function | For | If | Else | In | Let | Var => &self.keyword,
Struct | Function | For | If | Else | In | Let | Mut => &self.keyword,
BinaryInteger | OctalInteger | DecimalInteger => &self.literal,
SingleLineComment => &self.comment,
Error => &self.error,

View File

@ -13,12 +13,20 @@ impl<'a> ParseTree<'a> {
let mut declarations = Vec::new();
let mut associated_struct = None;
while let Some(tok) = lexer.next() {
if let Some(_) = associated_struct {
if tok != Token::Function {
lexer.panic_message("Expected fn");
if let Some(struct_name) = associated_struct {
let mut mutable = false;
if tok == Token::Mut {
mutable = true;
lexer.eat_expect(Token::Function);
} else if tok != Token::Function {
lexer.panic_message("Expected fn or mut");
}
declarations.push(Definition::build_function(associated_struct, lexer));
declarations.push(Definition::build_function(
Some((struct_name, mutable)),
lexer,
));
associated_struct = None;
} else {
match tok {
@ -26,7 +34,7 @@ impl<'a> ParseTree<'a> {
Token::Function => declarations.push(Definition::build_function(None, lexer)),
Token::Interface => declarations.push(Definition::build_interface(lexer)),
Token::Identifier => associated_struct = Some(lexer.slice()),
_ => lexer.panic_message("Expected associated struct identifier, fn or struct"),
_ => lexer.panic_message("Expected function, struct, or interface"),
}
}
}
@ -42,7 +50,7 @@ pub enum Definition<'a> {
members: Vec<StructMember<'a>>,
},
Function {
associated_struct: Option<&'a str>,
associated_struct: Option<(&'a str, bool)>,
name: &'a str,
signature: FnSig<'a>,
body: FnBody<'a>,
@ -78,7 +86,10 @@ impl<'a> Definition<'a> {
Self::Struct { name, members }
}
pub fn build_function(associated_struct: Option<&'a str>, lexer: &mut Lexer<'a>) -> Self {
pub fn build_function(
associated_struct: Option<(&'a str, bool)>,
lexer: &mut Lexer<'a>,
) -> Self {
let name = lexer.eat_expect_id();
let (signature, tok) = FnSig::build(lexer);
@ -204,15 +215,6 @@ impl<'a> FnBody<'a> {
_ => lexer.panic_message("Unexpected token"),
}
}
Token::Var => {
let (statement, next) = Statement::build_var(lexer);
statements.push(statement);
match next {
Token::Semicolon => {}
Token::BraceClose => break,
_ => lexer.panic_message("Unexpected token"),
}
}
Token::Identifier => match Expr::build_start(tok, lexer) {
(None, Token::Semicolon | Token::BraceClose) => {}
(Some(expr), Token::Semicolon) => statements.push(Statement::Expr(expr)),
@ -223,7 +225,7 @@ impl<'a> FnBody<'a> {
_ => lexer.panic_message("Unexpected token"),
},
Token::BraceClose => break,
_ => lexer.panic_message("Expected var, let, or assign"),
_ => lexer.panic_message("Expected let or expression"),
}
}
@ -294,6 +296,7 @@ pub enum BinaryOp {
Sub,
Mul,
Div,
Assign,
Less,
LessEq,
Greater,
@ -311,6 +314,7 @@ impl BinaryOp {
OpSub => Some(Sub),
OpMul => Some(Mul),
OpDiv => Some(Div),
OpAssign => Some(Assign),
OpLess => Some(Less),
OpLessEq => Some(LessEq),
OpGreater => Some(Greater),
@ -335,10 +339,7 @@ pub enum Statement<'a> {
Expr(Expr<'a>),
Let {
var: &'a str,
expr: Expr<'a>,
},
Var {
var: &'a str,
mutable: bool,
expr: Expr<'a>,
},
If {
@ -356,15 +357,18 @@ impl<'a> Statement<'a> {
}
pub fn build_let(lexer: &mut Lexer<'a>) -> (Self, Token) {
let var = lexer.eat_expect_id();
let (expr, tail) = Self::eat_assign(lexer);
(Self::Let { var, expr }, tail)
}
let mut mutable = false;
let var = match lexer.next().unwrap() {
Token::Identifier => lexer.slice(),
Token::Mut => {
mutable = true;
lexer.eat_expect_id()
}
_ => lexer.panic_message("Unexpected token"),
};
pub fn build_var(lexer: &mut Lexer<'a>) -> (Self, Token) {
let var = lexer.eat_expect_id();
let (expr, tail) = Self::eat_assign(lexer);
(Self::Var { var, expr }, tail)
(Self::Let { var, mutable, expr }, tail)
}
}

View File

@ -37,9 +37,9 @@ fn count_neighbors(BitArray array, i32 i, i32 j) i32 {
}
// associated function for the World struct
World fn set_next(i32 i, i32 j) {
World mut fn set_next(i32 i, i32 j) {
// members on this World struct can be accessed with `.`
var numdots = .numdots; // mutable variables are defined with `var`
let mut numdots = .numdots; // mutable variables are defined with `let mut`
let neighbors = count_neighbors(.current, i, j);
// `if` statements are expressions
@ -61,7 +61,6 @@ World fn set_next(i32 i, i32 j) {
};
if next != 0 {
// TODO: mutability rules for arguments?
if i < .xmin { .xmin = i; }
if i > .xmax { .xmax = i; }
if j < .ymin { .ymin = j; }
@ -85,7 +84,6 @@ World fn next_cycle() {
// TODO: figure out better range definitions, or ditch them altogether
for y in 0..(.ysize) {
for x in 0..(.xsize) {
// TODO: mutability rules
.current.set_bit(x, y, .next.get_bit(x, y));
}
}

View File

@ -3,9 +3,9 @@ fn free_floating(i32 arg1, i32 arg2) ReturnType {
}
// associated function for the World struct
World fn set_next(i32 i, i32 j) {
World mut fn set_next(i32 i, i32 j) {
// members on this World struct can be accessed with `.`
var numdots = .numdots; // mutable variables are defined with `var`
let mut numdots = .numdots; // mutable variables are defined with `let mut`
let neighbors = count_neighbors(.current, i, j);
// `if` statements are expressions
@ -27,7 +27,6 @@ World fn set_next(i32 i, i32 j) {
};
if next != 0 {
// TODO: mutability rules for arguments?
if i < .xmin { .xmin = i; }
if i > .xmax { .xmax = i; }
if j < .ymin { .ymin = j; }