aboutsummaryrefslogtreecommitdiffstats
path: root/src/compiler.rs
diff options
context:
space:
mode:
authorEdvard Thörnros <edvard.thornros@gmail.com>2021-02-08 14:18:05 +0100
committerGitHub <noreply@github.com>2021-02-08 14:18:05 +0100
commita41d008487c26dae5dcdf6e0be9323ad2e06c827 (patch)
tree45944ffa84770f3bf4ef09a3bbf5a002130e4468 /src/compiler.rs
parent98df292fe4142fcc836013341579ed4437a2a464 (diff)
parent1c9674e1a718397e48363743eb21638e2ccd6281 (diff)
downloadsylt-a41d008487c26dae5dcdf6e0be9323ad2e06c827.tar.gz
Merge pull request #55 from FredTheDino/op-copy
op copy
Diffstat (limited to 'src/compiler.rs')
-rw-r--r--src/compiler.rs55
1 files changed, 44 insertions, 11 deletions
diff --git a/src/compiler.rs b/src/compiler.rs
index d12ee4b..193d16c 100644
--- a/src/compiler.rs
+++ b/src/compiler.rs
@@ -117,6 +117,8 @@ pub(crate) struct Compiler {
blobs: Vec<Blob>,
functions: HashMap<String, (usize, RustFunction)>,
+ constants: Vec<Value>,
+ strings: Vec<String>,
}
macro_rules! push_frame {
@@ -187,9 +189,32 @@ impl Compiler {
blobs: Vec::new(),
functions: HashMap::new(),
+
+ constants: vec![Value::Nil],
+ strings: Vec::new(),
}
}
+ fn nil_value(&self) -> usize {
+ self.constants.iter()
+ .enumerate()
+ .find_map(|(i, x)|
+ match x {
+ Value::Nil => Some(i),
+ _ => None,
+ }).unwrap()
+ }
+
+ fn add_constant(&mut self, value: Value) -> usize {
+ self.constants.push(value);
+ self.constants.len() - 1
+ }
+
+ fn intern_string(&mut self, string: String) -> usize {
+ self.strings.push(string);
+ self.strings.len() - 1
+ }
+
fn frame(&self) -> &Frame {
let last = self.frames.len() - 1;
&self.frames[last]
@@ -336,7 +361,8 @@ impl Compiler {
Token::String(s) => { Value::String(Rc::from(s)) }
_ => { error!(self, "Cannot parse value."); Value::Bool(false) }
};
- add_op(self, block, Op::Constant(value));
+ let constant = self.add_constant(value);
+ add_op(self, block, Op::Constant(constant));
}
fn grouping_or_tuple(&mut self, block: &mut Block) {
@@ -586,7 +612,7 @@ impl Compiler {
Op::Pop | Op::PopUpvalue => {}
Op::Return => { break; } ,
_ => {
- add_op(self, &mut function_block, Op::Constant(Value::Nil));
+ add_op(self, &mut function_block, Op::Constant(self.nil_value()));
add_op(self, &mut function_block, Op::Return);
break;
}
@@ -594,7 +620,7 @@ impl Compiler {
}
if function_block.ops.is_empty() {
- add_op(self, &mut function_block, Op::Constant(Value::Nil));
+ add_op(self, &mut function_block, Op::Constant(self.nil_value()));
add_op(self, &mut function_block, Op::Return);
}
@@ -602,9 +628,9 @@ impl Compiler {
let function_block = Rc::new(RefCell::new(function_block));
- let func = Op::Constant(Value::Function(Vec::new(), Rc::clone(&function_block)));
+ let constant = self.add_constant(Value::Function(Vec::new(), Rc::clone(&function_block)));
self.blocks[block_id] = function_block;
- add_op(self, block, func);
+ add_op(self, block, Op::Constant(constant));
}
fn variable_expression(&mut self, block: &mut Block) {
@@ -623,7 +649,8 @@ impl Compiler {
Token::Dot => {
self.eat();
if let Token::Identifier(field) = self.eat() {
- add_op(self, block, Op::Get(String::from(field)));
+ let string = self.intern_string(String::from(field));
+ add_op(self, block, Op::Get(string));
} else {
error!(self, "Expected fieldname after '.'.");
break;
@@ -636,12 +663,14 @@ impl Compiler {
}
}
} else if let Some(blob) = self.find_blob(&name) {
- add_op(self, block, Op::Constant(Value::Blob(blob)));
+ let string = self.add_constant(Value::Blob(blob));
+ add_op(self, block, Op::Constant(string));
if self.peek() == Token::LeftParen {
self.call(block);
}
} else if let Some(slot) = self.find_extern_function(&name) {
- add_op(self, block, Op::Constant(Value::ExternFunction(slot)));
+ let string = self.add_constant(Value::ExternFunction(slot));
+ add_op(self, block, Op::Constant(string));
self.call(block);
} else {
error!(self, format!("Using undefined variable {}.", name));
@@ -675,7 +704,8 @@ impl Compiler {
fn definition_statement(&mut self, name: &str, typ: Type, block: &mut Block) {
let slot = self.define_variable(name, typ.clone(), block);
self.expression(block);
- add_op(self, block, Op::Define(typ));
+ let constant = self.add_constant(Value::Ty(typ));
+ add_op(self, block, Op::Define(constant));
if let Ok(slot) = slot {
self.stack_mut()[slot].active = true;
@@ -940,6 +970,7 @@ impl Compiler {
return Err(());
};
+ let field = self.intern_string(field);
let op = match self.peek() {
Token::Equal => {
self.eat();
@@ -959,7 +990,7 @@ impl Compiler {
}
};
add_op(self, block, Op::Copy);
- add_op(self, block, Op::Get(field.clone()));
+ add_op(self, block, Op::Get(field));
self.eat();
self.expression(block);
add_op(self, block, op);
@@ -1096,7 +1127,7 @@ impl Compiler {
self.statement(&mut block);
expect!(self, Token::Newline | Token::EOF, "Expect newline or EOF after expression.");
}
- add_op(self, &mut block, Op::Constant(Value::Nil));
+ add_op(self, &mut block, Op::Constant(self.nil_value()));
add_op(self, &mut block, Op::Return);
block.ty = Type::Function(Vec::new(), Box::new(Type::Void));
@@ -1107,6 +1138,8 @@ impl Compiler {
blocks: self.blocks.clone(),
blobs: self.blobs.iter().map(|x| Rc::new(x.clone())).collect(),
functions: functions.iter().map(|(_, f)| *f).collect(),
+ constants: self.constants.clone(),
+ strings: self.strings.clone(),
})
} else {
Err(self.errors.clone())