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("else")] Else,
#[token("in")] In, #[token("in")] In,
#[token("let")] Let, #[token("let")] Let,
#[token("var")] Var, #[token("mut")] Mut,
#[token("interface")] Interface, #[token("interface")] Interface,
#[token("impl")] Impl, #[token("impl")] Impl,

View File

@ -30,7 +30,7 @@ impl ColorTheme {
pub fn token_style(&self, token: &Token) -> &Style { pub fn token_style(&self, token: &Token) -> &Style {
use Token::*; use Token::*;
match 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, BinaryInteger | OctalInteger | DecimalInteger => &self.literal,
SingleLineComment => &self.comment, SingleLineComment => &self.comment,
Error => &self.error, Error => &self.error,

View File

@ -13,12 +13,20 @@ impl<'a> ParseTree<'a> {
let mut declarations = Vec::new(); let mut declarations = Vec::new();
let mut associated_struct = None; let mut associated_struct = None;
while let Some(tok) = lexer.next() { while let Some(tok) = lexer.next() {
if let Some(_) = associated_struct { if let Some(struct_name) = associated_struct {
if tok != Token::Function { let mut mutable = false;
lexer.panic_message("Expected fn"); 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; associated_struct = None;
} else { } else {
match tok { match tok {
@ -26,7 +34,7 @@ impl<'a> ParseTree<'a> {
Token::Function => declarations.push(Definition::build_function(None, lexer)), Token::Function => declarations.push(Definition::build_function(None, lexer)),
Token::Interface => declarations.push(Definition::build_interface(lexer)), Token::Interface => declarations.push(Definition::build_interface(lexer)),
Token::Identifier => associated_struct = Some(lexer.slice()), 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>>, members: Vec<StructMember<'a>>,
}, },
Function { Function {
associated_struct: Option<&'a str>, associated_struct: Option<(&'a str, bool)>,
name: &'a str, name: &'a str,
signature: FnSig<'a>, signature: FnSig<'a>,
body: FnBody<'a>, body: FnBody<'a>,
@ -78,7 +86,10 @@ impl<'a> Definition<'a> {
Self::Struct { name, members } 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 name = lexer.eat_expect_id();
let (signature, tok) = FnSig::build(lexer); let (signature, tok) = FnSig::build(lexer);
@ -204,15 +215,6 @@ impl<'a> FnBody<'a> {
_ => lexer.panic_message("Unexpected token"), _ => 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) { Token::Identifier => match Expr::build_start(tok, lexer) {
(None, Token::Semicolon | Token::BraceClose) => {} (None, Token::Semicolon | Token::BraceClose) => {}
(Some(expr), Token::Semicolon) => statements.push(Statement::Expr(expr)), (Some(expr), Token::Semicolon) => statements.push(Statement::Expr(expr)),
@ -223,7 +225,7 @@ impl<'a> FnBody<'a> {
_ => lexer.panic_message("Unexpected token"), _ => lexer.panic_message("Unexpected token"),
}, },
Token::BraceClose => break, 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, Sub,
Mul, Mul,
Div, Div,
Assign,
Less, Less,
LessEq, LessEq,
Greater, Greater,
@ -311,6 +314,7 @@ impl BinaryOp {
OpSub => Some(Sub), OpSub => Some(Sub),
OpMul => Some(Mul), OpMul => Some(Mul),
OpDiv => Some(Div), OpDiv => Some(Div),
OpAssign => Some(Assign),
OpLess => Some(Less), OpLess => Some(Less),
OpLessEq => Some(LessEq), OpLessEq => Some(LessEq),
OpGreater => Some(Greater), OpGreater => Some(Greater),
@ -335,10 +339,7 @@ pub enum Statement<'a> {
Expr(Expr<'a>), Expr(Expr<'a>),
Let { Let {
var: &'a str, var: &'a str,
expr: Expr<'a>, mutable: bool,
},
Var {
var: &'a str,
expr: Expr<'a>, expr: Expr<'a>,
}, },
If { If {
@ -356,15 +357,18 @@ impl<'a> Statement<'a> {
} }
pub fn build_let(lexer: &mut Lexer<'a>) -> (Self, Token) { pub fn build_let(lexer: &mut Lexer<'a>) -> (Self, Token) {
let var = lexer.eat_expect_id(); let mut mutable = false;
let (expr, tail) = Self::eat_assign(lexer); let var = match lexer.next().unwrap() {
(Self::Let { var, expr }, tail) 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); 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 // 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 `.` // 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); let neighbors = count_neighbors(.current, i, j);
// `if` statements are expressions // `if` statements are expressions
@ -61,7 +61,6 @@ World fn set_next(i32 i, i32 j) {
}; };
if next != 0 { if next != 0 {
// TODO: mutability rules for arguments?
if i < .xmin { .xmin = i; } if i < .xmin { .xmin = i; }
if i > .xmax { .xmax = i; } if i > .xmax { .xmax = i; }
if j < .ymin { .ymin = j; } if j < .ymin { .ymin = j; }
@ -85,7 +84,6 @@ World fn next_cycle() {
// TODO: figure out better range definitions, or ditch them altogether // TODO: figure out better range definitions, or ditch them altogether
for y in 0..(.ysize) { for y in 0..(.ysize) {
for x in 0..(.xsize) { for x in 0..(.xsize) {
// TODO: mutability rules
.current.set_bit(x, y, .next.get_bit(x, y)); .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 // 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 `.` // 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); let neighbors = count_neighbors(.current, i, j);
// `if` statements are expressions // `if` statements are expressions
@ -27,7 +27,6 @@ World fn set_next(i32 i, i32 j) {
}; };
if next != 0 { if next != 0 {
// TODO: mutability rules for arguments?
if i < .xmin { .xmin = i; } if i < .xmin { .xmin = i; }
if i > .xmax { .xmax = i; } if i > .xmax { .xmax = i; }
if j < .ymin { .ymin = j; } if j < .ymin { .ymin = j; }