Skip to content

Commit b917efa

Browse files
committed
Add compilation of lambdas and support function arguments.
1 parent 976c1f4 commit b917efa

3 files changed

Lines changed: 29 additions & 6 deletions

File tree

vm/src/bytecode.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,15 @@ use std::fmt;
1717
pub struct CodeObject {
1818
pub instructions: Vec<Instruction>,
1919
pub label_map: HashMap<Label, usize>,
20+
pub arg_names: Vec<String>,
2021
}
2122

2223
impl CodeObject {
23-
pub fn new() -> CodeObject {
24+
pub fn new(arg_names : Vec<String>) -> CodeObject {
2425
CodeObject {
2526
instructions: Vec::new(),
2627
label_map: HashMap::new(),
28+
arg_names: arg_names,
2729
}
2830
}
2931
}

vm/src/compile.rs

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ struct Compiler {
1515

1616
pub fn compile(rt: &mut Executor, source: &String, mode: Mode) -> Result<PyObjectRef, String> {
1717
let mut compiler = Compiler::new();
18-
compiler.push_code_object(CodeObject::new());
18+
compiler.push_code_object(CodeObject::new(Vec::new()));
1919
match mode {
2020
Mode::Exec => match parser::parse_program(source) {
2121
Ok(ast) => {
@@ -62,7 +62,7 @@ impl Compiler {
6262
}
6363

6464
fn push_code_object(&mut self, code_object: CodeObject) {
65-
self.code_object_stack.push(CodeObject::new());
65+
self.code_object_stack.push(CodeObject::new(Vec::new()));
6666
}
6767

6868
fn pop_code_object(&mut self) -> CodeObject {
@@ -191,7 +191,7 @@ impl Compiler {
191191
}
192192
ast::Statement::FunctionDef { name, args, body } => {
193193
// Create bytecode for this function:
194-
self.code_object_stack.push(CodeObject::new());
194+
self.code_object_stack.push(CodeObject::new(args.to_vec()));
195195
self.compile_statements(body);
196196
let code = self.code_object_stack.pop().unwrap();
197197
self.emit(Instruction::LoadConst {
@@ -444,6 +444,22 @@ impl Compiler {
444444
name: name.to_string(),
445445
});
446446
}
447+
ast::Expression::Lambda { args, body } => {
448+
self.code_object_stack.push(CodeObject::new(args.to_vec()));
449+
self.compile_expression(body);
450+
self.emit(Instruction::ReturnValue);
451+
let code = self.code_object_stack.pop().unwrap();
452+
self.emit(Instruction::LoadConst {
453+
value: bytecode::Constant::Code { code: code },
454+
});
455+
self.emit(Instruction::LoadConst {
456+
value: bytecode::Constant::String {
457+
value: String::from("<lambda>"),
458+
},
459+
});
460+
// Turn code object into function object:
461+
self.emit(Instruction::MakeFunction);
462+
}
447463
}
448464
}
449465

vm/src/vm.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use std::ops::Deref;
1010

1111
use super::builtins;
1212
use super::bytecode;
13-
use super::frame::{Block, Frame};
13+
use super::frame::{Block, Frame, copy_code};
1414
use super::import::import;
1515
use super::objlist;
1616
use super::objstr;
@@ -431,7 +431,12 @@ impl VirtualMachine {
431431
match f.kind {
432432
PyObjectKind::RustFunction { ref function } => f.call(self, args),
433433
PyObjectKind::Function { ref code } => {
434-
let frame = Frame::new(code.clone(), HashMap::new(), self.new_dict());
434+
let mut locals = self.new_dict();
435+
let code_object = copy_code(code.clone());
436+
for (name, value) in code_object.arg_names.iter().zip(args) {
437+
locals.set_item(name, value);
438+
}
439+
let frame = Frame::new(code.clone(), HashMap::new(), locals);
435440
self.run_frame(frame)
436441
}
437442
PyObjectKind::Class { name: _ } => self.new_instance(func_ref.clone(), args),

0 commit comments

Comments
 (0)