Skip to content

Commit 9a3b731

Browse files
authored
Merge pull request RustPython#612 from RustPython/type_annotations2
Compile type annotations on function.
2 parents 8362b8d + 502f809 commit 9a3b731

File tree

4 files changed

+58
-4
lines changed

4 files changed

+58
-4
lines changed

tests/snippets/type_hints.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
# See also: https://github.com/RustPython/RustPython/issues/587
33

4-
def curry(foo: int) -> float:
5-
return foo * 3.1415926 * 2
4+
def curry(foo: int, bla=2) -> float:
5+
return foo * 3.1415926 * bla
66

77
assert curry(2) > 10

vm/src/bytecode.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ pub struct CodeObject {
3131
bitflags! {
3232
pub struct FunctionOpArg: u8 {
3333
const HAS_DEFAULTS = 0x01;
34+
const HAS_ANNOTATIONS = 0x04;
3435
}
3536
}
3637

vm/src/compile.rs

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -595,15 +595,15 @@ impl Compiler {
595595
args: &ast::Parameters,
596596
body: &[ast::LocatedStatement],
597597
decorator_list: &[ast::Expression],
598-
_returns: &Option<ast::Expression>, // TODO: use type hint somehow..
598+
returns: &Option<ast::Expression>, // TODO: use type hint somehow..
599599
) -> Result<(), CompileError> {
600600
// Create bytecode for this function:
601601
// remember to restore self.in_loop to the original after the function is compiled
602602
let was_in_loop = self.in_loop;
603603
let was_in_function_def = self.in_function_def;
604604
self.in_loop = false;
605605
self.in_function_def = true;
606-
let flags = self.enter_function(name, args)?;
606+
let mut flags = self.enter_function(name, args)?;
607607
self.compile_statements(body)?;
608608

609609
// Emit None at end:
@@ -614,6 +614,43 @@ impl Compiler {
614614
let code = self.pop_code_object();
615615

616616
self.prepare_decorators(decorator_list)?;
617+
618+
// Prepare type annotations:
619+
let mut num_annotations = 0;
620+
621+
// Return annotation:
622+
if let Some(annotation) = returns {
623+
// key:
624+
self.emit(Instruction::LoadConst {
625+
value: bytecode::Constant::String {
626+
value: "return".to_string(),
627+
},
628+
});
629+
// value:
630+
self.compile_expression(annotation)?;
631+
num_annotations += 1;
632+
}
633+
634+
for arg in args.args.iter() {
635+
if let Some(annotation) = &arg.annotation {
636+
self.emit(Instruction::LoadConst {
637+
value: bytecode::Constant::String {
638+
value: arg.arg.to_string(),
639+
},
640+
});
641+
self.compile_expression(&annotation)?;
642+
num_annotations += 1;
643+
}
644+
}
645+
646+
if num_annotations > 0 {
647+
flags |= bytecode::FunctionOpArg::HAS_ANNOTATIONS;
648+
self.emit(Instruction::BuildMap {
649+
size: num_annotations,
650+
unpack: false,
651+
});
652+
}
653+
617654
self.emit(Instruction::LoadConst {
618655
value: bytecode::Constant::Code {
619656
code: Box::new(code),

vm/src/frame.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,15 +452,31 @@ impl Frame {
452452
bytecode::Instruction::MakeFunction { flags } => {
453453
let _qualified_name = self.pop_value();
454454
let code_obj = self.pop_value();
455+
456+
let _annotations = if flags.contains(bytecode::FunctionOpArg::HAS_ANNOTATIONS) {
457+
self.pop_value()
458+
} else {
459+
vm.new_dict()
460+
};
461+
455462
let defaults = if flags.contains(bytecode::FunctionOpArg::HAS_DEFAULTS) {
456463
self.pop_value()
457464
} else {
458465
vm.get_none()
459466
};
467+
460468
// pop argc arguments
461469
// argument: name, args, globals
462470
let scope = self.scope.clone();
463471
let obj = vm.ctx.new_function(code_obj, scope, defaults);
472+
473+
let annotation_repr = vm.to_pystr(&_annotations)?;
474+
475+
warn!(
476+
"Type annotation must be stored in attribute! {:?}",
477+
annotation_repr
478+
);
479+
// TODO: use annotations with set_attr here!
464480
self.push_value(obj);
465481
Ok(None)
466482
}

0 commit comments

Comments
 (0)