Skip to content

Commit

Permalink
Immutables
Browse files Browse the repository at this point in the history
  • Loading branch information
nic-gaffney committed Sep 6, 2023
1 parent 7275a60 commit 5711de4
Show file tree
Hide file tree
Showing 9 changed files with 112 additions and 4 deletions.
1 change: 1 addition & 0 deletions build.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Build Sloth
cargo build
rm output.o
FILENAME="$1"
# Compile standard library
./target/debug/sloth std/extern.sloth std/stdmath.sloth std/stdio.sloth $FILENAME
Expand Down
7 changes: 7 additions & 0 deletions examples/mutable.sloth
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
fn main() {
val test = 0;
println(istr(test));
#test = 1;
println(istr(test));
return 0;
}
26 changes: 25 additions & 1 deletion sloth/src/analysis/setup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,22 @@ impl Populator {
name: "Float".to_owned(),
is_list: false,
}),
true,
)?;
table.insert(identifier.to_owned(), symbol);
}
StmtKind::DefineValue {
identifier, typ, ..
} => {
// When a variable is defined add it to the symbol table of the current scope.
let symbol = self.build_value_symbol(
node.line(),
&table,
&typ.clone().unwrap_or(TypeIdentifier {
name: "Float".to_owned(),
is_list: false,
}),
false,
)?;
table.insert(identifier.to_owned(), symbol);
}
Expand All @@ -56,7 +72,7 @@ impl Populator {

for input in inputs {
let symbol =
self.build_value_symbol(node.line(), &body_table, &input.typ)?;
self.build_value_symbol(node.line(), &body_table, &input.typ, true)?;
body_table.insert(input.identifier.to_owned(), symbol);
}
}
Expand All @@ -70,6 +86,7 @@ impl Populator {
let symbol = Symbol::Value(ValueSymbol {
typ: Type::Integer,
id: self.reserve_id(),
mutable: true,
});

body_table.insert(identifier.to_owned(), symbol);
Expand All @@ -90,6 +107,7 @@ impl Populator {
line: u32,
table: &SymbolTable,
typ: &TypeIdentifier,
mutab: bool,
) -> Result<Symbol, AnalysisError> {
let typ = table
.get_type(typ)
Expand All @@ -98,6 +116,7 @@ impl Populator {
Ok(Symbol::Value(ValueSymbol {
typ,
id: self.reserve_id(),
mutable: mutab,
}))
}

Expand Down Expand Up @@ -129,8 +148,10 @@ impl Populator {
typ: Type::Function {
inputs,
output: output.into(),

},
id: self.reserve_id(),
mutable: true,
}))
}
}
Expand Down Expand Up @@ -167,6 +188,9 @@ pub(super) fn propagate_types_stmt(node: &mut Stmt) -> Result<(), AnalysisError>
StmtKind::DefineVariable { value, .. } => {
propagate_types(value)?;
}
StmtKind::DefineValue { value, .. } => {
propagate_types(value)?;
}
StmtKind::AssignVariable { value, .. } => {
propagate_types(value)?;
}
Expand Down
21 changes: 18 additions & 3 deletions sloth/src/codegen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,14 +233,29 @@ impl<'ctx> Codegen<'ctx> {
self.builder.build_store(ptr, init_value);
self.references.insert(symbol.id, ptr);
}
StmtKind::AssignVariable { identifier, value } => {
StmtKind::DefineValue {
identifier, value, ..
} => {
let table = code.symtable.clone();
let symbol = table.get_value(identifier).unwrap();

let ptr = self.references.get(&symbol.id).unwrap();
let ptr = self.codegen_alloca(self.type_as_basic_type(symbol.typ), identifier);
let init_value = self.codegen_expr(value).unwrap();

self.builder.build_store(*ptr, init_value);
self.builder.build_store(ptr, init_value);
self.references.insert(symbol.id, ptr);
}
StmtKind::AssignVariable { identifier, value } => {
let table = code.symtable.clone();
let symbol = table.get_value(identifier).unwrap();
if symbol.mutable {
let ptr = self.references.get(&symbol.id).unwrap();
let init_value = self.codegen_expr(value).unwrap();

self.builder.build_store(*ptr, init_value);
} else {
panic!("Val not mutable!");
}
}
StmtKind::DefineFunction(function) => {
let table = code.symtable.clone();
Expand Down
4 changes: 4 additions & 0 deletions sloth/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ fn mk_symtable() -> SymbolTable {
output: Box::new(Type::Integer),
},
id: 0,
mutable: true,
});

let dummyf = Symbol::Value(ValueSymbol {
Expand All @@ -108,6 +109,7 @@ fn mk_symtable() -> SymbolTable {
output: Box::new(Type::Float),
},
id: 0,
mutable: true,
});

let dummyb = Symbol::Value(ValueSymbol {
Expand All @@ -116,6 +118,7 @@ fn mk_symtable() -> SymbolTable {
output: Box::new(Type::Boolean),
},
id: 0,
mutable: true,
});

let dummys = Symbol::Value(ValueSymbol {
Expand All @@ -124,6 +127,7 @@ fn mk_symtable() -> SymbolTable {
output: Box::new(Type::Boolean),
},
id: 0,
mutable: true,
});

global_symtable.insert("vlen".into(), dummyi.clone());
Expand Down
6 changes: 6 additions & 0 deletions sloth/src/parser/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ impl Stmt {
children.push(body.as_node());
}
StmtKind::DefineVariable { value, .. } => children.push(value.as_node()),
StmtKind::DefineValue { value, .. } => children.push(value.as_node()),
StmtKind::AssignVariable { value, .. } => children.push(value.as_node()),
StmtKind::DefineFunction(Function { kind, .. }) => {
if let FunctionKind::Normal { body } = kind {
Expand Down Expand Up @@ -233,6 +234,11 @@ pub enum StmtKind {
value: Expr,
typ: Option<TypeIdentifier>,
},
DefineValue {
identifier: String,
value: Expr,
typ: Option<TypeIdentifier>,
},
AssignVariable {
identifier: String,
value: Expr,
Expand Down
18 changes: 18 additions & 0 deletions sloth/src/parser/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,20 @@ impl GraphBuilder {
self.traverse_expr0(iterator)?;
self.traverse_stmt0(body)?;
}
StmtKind::DefineValue {
identifier,
value,
typ,
} => {
writeln!(
&mut self.graph,
"N{} [shape=box label=\"DefineValue\\n\\nIdentifier={}\\lType={}\\l\"];",
stmt.id,
identifier,
typ.clone().unwrap()
)?;
self.traverse_expr0(value)?;
}
StmtKind::DefineVariable {
identifier,
value,
Expand Down Expand Up @@ -277,6 +291,10 @@ impl GraphBuilder {
writeln!(&mut self.graph, "N{} -> N{};", stmt.id, value.id)?;
self.traverse_expr(value)?;
}
StmtKind::DefineValue { value, .. } => {
writeln!(&mut self.graph, "N{} -> N{};", stmt.id, value.id)?;
self.traverse_expr(value)?;
}
StmtKind::AssignVariable { value, .. } => {
writeln!(&mut self.graph, "N{} -> N{};", stmt.id, value.id)?;
self.traverse_expr(value)?;
Expand Down
32 changes: 32 additions & 0 deletions sloth/src/parser/stmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ impl<'a> AstParser<'a> {
TokenType::While => self.while_stmt(),
TokenType::For => self.for_stmt(),
TokenType::Var => self.define_variable(),
TokenType::Val => self.define_value(),
TokenType::Fn => self.define_function(false),
TokenType::Return => self.return_stmt(),

Expand Down Expand Up @@ -149,6 +150,37 @@ impl<'a> AstParser<'a> {
))
}

fn define_value(&mut self) -> Result<Stmt, ParsingError> {
// Consume the val token
self.consume(TokenType::Val, "Expected val")?;

// Get the identifier and type
let identifier = self.consume_identifier()?;
let typ = if self.consume(TokenType::Colon, "Expected ':'").is_ok() {
self.consume_type().ok()
} else {
None
};

// Get the default value
self.consume(TokenType::Eq, "Expected '='")?;
let value = self.expression()?;

self.consume(TokenType::SemiColon, "Expected ';' at end of statement")?;

let kind = StmtKind::DefineValue {
identifier,
value,
typ,
};

Ok(Stmt::new(
self.reserve_id(),
self.line,
kind,
self.top.clone(),
))
}
// TODO: Make argument types optional
fn define_function(&mut self, is_foreign: bool) -> Result<Stmt, ParsingError> {
// Consume the fn token
Expand Down
1 change: 1 addition & 0 deletions sloth/src/symtable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ pub enum Symbol {
pub struct ValueSymbol {
pub typ: Type,
pub id: i32,
pub mutable: bool,
}

#[derive(Clone, Debug, PartialEq, PartialOrd)]
Expand Down

0 comments on commit 5711de4

Please sign in to comment.