aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xbuild.sh1
-rw-r--r--examples/mutable.sloth7
-rw-r--r--sloth/src/analysis/setup.rs26
-rw-r--r--sloth/src/codegen/mod.rs21
-rw-r--r--sloth/src/main.rs4
-rw-r--r--sloth/src/parser/ast.rs6
-rw-r--r--sloth/src/parser/graph.rs18
-rw-r--r--sloth/src/parser/stmt.rs32
-rw-r--r--sloth/src/symtable.rs1
9 files changed, 112 insertions, 4 deletions
diff --git a/build.sh b/build.sh
index cbcd805..f6ad2e3 100755
--- a/build.sh
+++ b/build.sh
@@ -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
diff --git a/examples/mutable.sloth b/examples/mutable.sloth
new file mode 100644
index 0000000..7ea6a96
--- /dev/null
+++ b/examples/mutable.sloth
@@ -0,0 +1,7 @@
+fn main() {
+ val test = 0;
+ println(istr(test));
+ #test = 1;
+ println(istr(test));
+ return 0;
+}
diff --git a/sloth/src/analysis/setup.rs b/sloth/src/analysis/setup.rs
index 3110f77..522d757 100644
--- a/sloth/src/analysis/setup.rs
+++ b/sloth/src/analysis/setup.rs
@@ -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);
}
@@ -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);
}
}
@@ -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);
@@ -90,6 +107,7 @@ impl Populator {
line: u32,
table: &SymbolTable,
typ: &TypeIdentifier,
+ mutab: bool,
) -> Result<Symbol, AnalysisError> {
let typ = table
.get_type(typ)
@@ -98,6 +116,7 @@ impl Populator {
Ok(Symbol::Value(ValueSymbol {
typ,
id: self.reserve_id(),
+ mutable: mutab,
}))
}
@@ -129,8 +148,10 @@ impl Populator {
typ: Type::Function {
inputs,
output: output.into(),
+
},
id: self.reserve_id(),
+ mutable: true,
}))
}
}
@@ -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)?;
}
diff --git a/sloth/src/codegen/mod.rs b/sloth/src/codegen/mod.rs
index 59f1ea6..7678856 100644
--- a/sloth/src/codegen/mod.rs
+++ b/sloth/src/codegen/mod.rs
@@ -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();
diff --git a/sloth/src/main.rs b/sloth/src/main.rs
index c181a3b..23946b2 100644
--- a/sloth/src/main.rs
+++ b/sloth/src/main.rs
@@ -100,6 +100,7 @@ fn mk_symtable() -> SymbolTable {
output: Box::new(Type::Integer),
},
id: 0,
+ mutable: true,
});
let dummyf = Symbol::Value(ValueSymbol {
@@ -108,6 +109,7 @@ fn mk_symtable() -> SymbolTable {
output: Box::new(Type::Float),
},
id: 0,
+ mutable: true,
});
let dummyb = Symbol::Value(ValueSymbol {
@@ -116,6 +118,7 @@ fn mk_symtable() -> SymbolTable {
output: Box::new(Type::Boolean),
},
id: 0,
+ mutable: true,
});
let dummys = Symbol::Value(ValueSymbol {
@@ -124,6 +127,7 @@ fn mk_symtable() -> SymbolTable {
output: Box::new(Type::Boolean),
},
id: 0,
+ mutable: true,
});
global_symtable.insert("vlen".into(), dummyi.clone());
diff --git a/sloth/src/parser/ast.rs b/sloth/src/parser/ast.rs
index 74500ef..7bc2c1b 100644
--- a/sloth/src/parser/ast.rs
+++ b/sloth/src/parser/ast.rs
@@ -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 {
@@ -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,
diff --git a/sloth/src/parser/graph.rs b/sloth/src/parser/graph.rs
index 7b56b56..a76bf4c 100644
--- a/sloth/src/parser/graph.rs
+++ b/sloth/src/parser/graph.rs
@@ -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,
@@ -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)?;
diff --git a/sloth/src/parser/stmt.rs b/sloth/src/parser/stmt.rs
index 75ef1b2..54534c4 100644
--- a/sloth/src/parser/stmt.rs
+++ b/sloth/src/parser/stmt.rs
@@ -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(),
@@ -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
diff --git a/sloth/src/symtable.rs b/sloth/src/symtable.rs
index 549bb59..06c0026 100644
--- a/sloth/src/symtable.rs
+++ b/sloth/src/symtable.rs
@@ -143,6 +143,7 @@ pub enum Symbol {
pub struct ValueSymbol {
pub typ: Type,
pub id: i32,
+ pub mutable: bool,
}
#[derive(Clone, Debug, PartialEq, PartialOrd)]