Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Move varargs information into CodeFlags
  • Loading branch information
coolreader18 committed Apr 2, 2020
commit 6553bf72d40a0b9b700c2db72f4de64dcaedeafc
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions bytecode/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ lz4-compress = "0.1.1"
num-bigint = { version = "0.2", features = ["serde"] }
num-complex = { version = "0.2", features = ["serde"] }
serde = { version = "1.0", features = ["derive"] }
itertools = "0.8"
47 changes: 34 additions & 13 deletions bytecode/src/bytecode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
//! implements bytecode structure.

use bitflags::bitflags;
use itertools::Itertools;
use num_bigint::BigInt;
use num_complex::Complex64;
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -40,9 +41,9 @@ pub struct CodeObject {
pub flags: CodeFlags,
pub posonlyarg_count: usize, // Number of positional-only arguments
pub arg_names: Vec<String>, // Names of positional arguments
pub varargs: Varargs, // *args or *
pub varargs_name: Option<String>, // *args or *
pub kwonlyarg_names: Vec<String>,
pub varkeywords: Varargs, // **kwargs or **
pub varkeywords_name: Option<String>, // **kwargs or **
pub source_path: String,
pub first_line_number: usize,
pub obj_name: String, // Name of the object that created this code object
Expand All @@ -57,6 +58,8 @@ bitflags! {
const NEW_LOCALS = 0x08;
const IS_GENERATOR = 0x10;
const IS_COROUTINE = 0x20;
const HAS_VARARGS = 0x40;
const HAS_VARKEYWORDS = 0x80;
}
}

Expand All @@ -70,6 +73,8 @@ impl CodeFlags {
pub const NAME_MAPPING: &'static [(&'static str, CodeFlags)] = &[
("GENERATOR", CodeFlags::IS_GENERATOR),
("COROUTINE", CodeFlags::IS_COROUTINE),
("VARARGS", CodeFlags::HAS_VARARGS),
("VARKEYWORDS", CodeFlags::HAS_VARKEYWORDS),
];
}

Expand Down Expand Up @@ -352,13 +357,6 @@ pub enum UnaryOperator {
Plus,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Varargs {
None,
Unnamed,
Named(String),
}

/*
Maintain a stack of blocks on the VM.
pub enum BlockType {
Expand All @@ -373,9 +371,9 @@ impl CodeObject {
flags: CodeFlags,
posonlyarg_count: usize,
arg_names: Vec<String>,
varargs: Varargs,
varargs_name: Option<String>,
kwonlyarg_names: Vec<String>,
varkeywords: Varargs,
varkeywords_name: Option<String>,
source_path: String,
first_line_number: usize,
obj_name: String,
Expand All @@ -387,9 +385,9 @@ impl CodeObject {
flags,
posonlyarg_count,
arg_names,
varargs,
varargs_name,
kwonlyarg_names,
varkeywords,
varkeywords_name,
source_path,
first_line_number,
obj_name,
Expand Down Expand Up @@ -418,6 +416,29 @@ impl CodeObject {
})
}

pub fn varnames(&self) -> impl Iterator<Item = &str> + '_ {
self.arg_names
.iter()
.map(String::as_str)
.chain(self.kwonlyarg_names.iter().map(String::as_str))
.chain(
self.instructions
.iter()
.filter_map(|i| match i {
Instruction::LoadName {
name,
scope: NameScope::Local,
}
| Instruction::StoreName {
name,
scope: NameScope::Local,
} => Some(name.as_str()),
_ => None,
})
.unique(),
)
}

fn display_inner(
&self,
f: &mut fmt::Formatter,
Expand Down
41 changes: 24 additions & 17 deletions compiler/src/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use crate::symboltable::{
};
use itertools::Itertools;
use num_complex::Complex64;
use rustpython_bytecode::bytecode::{self, CallType, CodeObject, Instruction, Label, Varargs};
use rustpython_bytecode::bytecode::{self, CallType, CodeObject, Instruction, Label};
use rustpython_parser::{ast, parser};

type BasicOutputStream = PeepholeOptimizer<CodeObjectStream>;
Expand Down Expand Up @@ -177,9 +177,9 @@ impl<O: OutputStream> Compiler<O> {
Default::default(),
0,
Vec::new(),
Varargs::None,
None,
Vec::new(),
Varargs::None,
None,
self.source_path.clone().unwrap(),
line_number,
obj_name,
Expand Down Expand Up @@ -686,14 +686,29 @@ impl<O: OutputStream> Compiler<O> {
flags |= bytecode::CodeFlags::HAS_KW_ONLY_DEFAULTS;
}

let mut compile_varargs = |va: &ast::Varargs, flag| match va {
ast::Varargs::None => None,
ast::Varargs::Unnamed => {
flags |= flag;
None
}
ast::Varargs::Named(name) => {
flags |= flag;
Some(name.arg.clone())
}
};

let varargs_name = compile_varargs(&args.vararg, bytecode::CodeFlags::HAS_VARARGS);
let varkeywords_name = compile_varargs(&args.kwarg, bytecode::CodeFlags::HAS_VARKEYWORDS);

let line_number = self.get_source_line_number();
self.push_output(CodeObject::new(
flags,
args.posonlyargs_count,
args.args.iter().map(|a| a.arg.clone()).collect(),
compile_varargs(&args.vararg),
varargs_name,
args.kwonlyargs.iter().map(|a| a.arg.clone()).collect(),
compile_varargs(&args.kwarg),
varkeywords_name,
self.source_path.clone().unwrap(),
line_number,
name.to_owned(),
Expand Down Expand Up @@ -970,9 +985,9 @@ impl<O: OutputStream> Compiler<O> {
Default::default(),
0,
vec![],
Varargs::None,
None,
vec![],
Varargs::None,
None,
self.source_path.clone().unwrap(),
line_number,
name.to_owned(),
Expand Down Expand Up @@ -1920,9 +1935,9 @@ impl<O: OutputStream> Compiler<O> {
Default::default(),
1,
vec![".0".to_owned()],
Varargs::None,
None,
vec![],
Varargs::None,
None,
self.source_path.clone().unwrap(),
line_number,
name.clone(),
Expand Down Expand Up @@ -2223,14 +2238,6 @@ fn compile_location(location: &ast::Location) -> bytecode::Location {
bytecode::Location::new(location.row(), location.column())
}

fn compile_varargs(varargs: &ast::Varargs) -> bytecode::Varargs {
match varargs {
ast::Varargs::None => bytecode::Varargs::None,
ast::Varargs::Unnamed => bytecode::Varargs::Unnamed,
ast::Varargs::Named(param) => bytecode::Varargs::Named(param.arg.clone()),
}
}

fn compile_conversion_flag(conversion_flag: ast::ConversionFlag) -> bytecode::ConversionFlag {
match conversion_flag {
ast::ConversionFlag::Ascii => bytecode::ConversionFlag::Ascii,
Expand Down
10 changes: 10 additions & 0 deletions vm/src/obj/objcode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,16 @@ impl PyCodeRef {
fn co_flags(self) -> u8 {
self.code.flags.bits()
}

#[pyproperty]
fn co_varnames(self, vm: &VirtualMachine) -> PyObjectRef {
let varnames = self
.code
.varnames()
.map(|s| vm.new_str(s.to_owned()))
.collect();
vm.ctx.new_tuple(varnames)
}
}

pub fn init(ctx: &PyContext) {
Expand Down
48 changes: 24 additions & 24 deletions vm/src/obj/objfunction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,37 +93,37 @@ impl PyFunction {
}

// Pack other positional arguments in to *args:
match code_object.varargs {
bytecode::Varargs::Named(ref vararg_name) => {
let mut last_args = vec![];
for i in n..nargs {
let arg = &func_args.args[i];
last_args.push(arg.clone());
}
let vararg_value = vm.ctx.new_tuple(last_args);

locals.set_item(vararg_name, vararg_value, vm)?;
if let Some(ref vararg_name) = code_object.varargs_name {
let mut last_args = vec![];
for i in n..nargs {
let arg = &func_args.args[i];
last_args.push(arg.clone());
}
bytecode::Varargs::Unnamed | bytecode::Varargs::None => {
// Check the number of positional arguments
if nargs > nexpected_args {
return Err(vm.new_type_error(format!(
"Expected {} arguments (got: {})",
nexpected_args, nargs
)));
}
let vararg_value = vm.ctx.new_tuple(last_args);

locals.set_item(vararg_name, vararg_value, vm)?;
} else {
// Check the number of positional arguments
if nargs > nexpected_args {
return Err(vm.new_type_error(format!(
"Expected {} arguments (got: {})",
nexpected_args, nargs
)));
}
}

// Do we support `**kwargs` ?
let kwargs = match code_object.varkeywords {
bytecode::Varargs::Named(ref kwargs_name) => {
let d = vm.ctx.new_dict();
let kwargs = if code_object
.flags
.contains(bytecode::CodeFlags::HAS_VARKEYWORDS)
{
let d = vm.ctx.new_dict();
if let Some(ref kwargs_name) = code_object.varkeywords_name {
locals.set_item(kwargs_name, d.as_object().clone(), vm)?;
Some(d)
}
bytecode::Varargs::Unnamed => Some(vm.ctx.new_dict()),
bytecode::Varargs::None => None,
Some(d)
} else {
None
};

// Handle keyword arguments
Expand Down