Skip to content

Convert re to new style args #761

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 29, 2019
Merged
Changes from all commits
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
184 changes: 56 additions & 128 deletions vm/src/stdlib/re.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,9 @@
*/
use regex::{Match, Regex};

use crate::function::PyFuncArgs;
use crate::obj::objstr;
use crate::obj::objstr::PyStringRef;
use crate::obj::objtype::PyClassRef;
use crate::pyobject::{PyContext, PyObjectRef, PyRef, PyResult, PyValue, TypeProtocol};
use crate::pyobject::{PyContext, PyObjectRef, PyRef, PyResult, PyValue};
use crate::vm::VirtualMachine;

impl PyValue for Regex {
Expand All @@ -19,73 +17,39 @@ impl PyValue for Regex {
}
}

/// Create the python `re` module with all its members.
pub fn make_module(ctx: &PyContext) -> PyObjectRef {
let match_type = py_class!(ctx, "Match", ctx.object(), {
"start" => ctx.new_rustfunc(match_start),
"end" => ctx.new_rustfunc(match_end)
});

let pattern_type = py_class!(ctx, "Pattern", ctx.object(), {
"match" => ctx.new_rustfunc(pattern_match),
"search" => ctx.new_rustfunc(pattern_search)
});
/// Inner data for a match object.
#[derive(Debug)]
struct PyMatch {
start: usize,
end: usize,
}

py_module!(ctx, "re", {
"compile" => ctx.new_rustfunc(re_compile),
"Match" => match_type,
"match" => ctx.new_rustfunc(re_match),
"Pattern" => pattern_type,
"search" => ctx.new_rustfunc(re_search)
})
impl PyValue for PyMatch {
fn class(vm: &VirtualMachine) -> PyClassRef {
vm.class("re", "Match")
}
}

/// Implement re.match
/// See also:
/// https://docs.python.org/3/library/re.html#re.match
fn re_match(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(
vm,
args,
required = [
(pattern, Some(vm.ctx.str_type())),
(string, Some(vm.ctx.str_type()))
]
);
let pattern_str = objstr::get_value(&pattern);
let regex = make_regex(vm, &pattern_str)?;
let search_text = objstr::get_value(string);

do_match(vm, &regex, search_text)
type PyRegexRef = PyRef<Regex>;
type PyMatchRef = PyRef<PyMatch>;

fn re_match(pattern: PyStringRef, string: PyStringRef, vm: &VirtualMachine) -> PyResult {
let regex = make_regex(vm, &pattern.value)?;
do_match(vm, &regex, &string.value)
}

/// Implement re.search
/// See also:
/// https://docs.python.org/3/library/re.html#re.search
fn re_search(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(
vm,
args,
required = [
(pattern, Some(vm.ctx.str_type())),
(string, Some(vm.ctx.str_type()))
]
);

let pattern_str = objstr::get_value(&pattern);
let regex = make_regex(vm, &pattern_str)?;
let search_text = objstr::get_value(string);

do_search(vm, &regex, search_text)
fn re_search(pattern: PyStringRef, string: PyStringRef, vm: &VirtualMachine) -> PyResult {
let regex = make_regex(vm, &pattern.value)?;
do_search(vm, &regex, &string.value)
}

fn do_match(vm: &VirtualMachine, regex: &Regex, search_text: String) -> PyResult {
fn do_match(vm: &VirtualMachine, regex: &Regex, search_text: &str) -> PyResult {
// TODO: implement match!
do_search(vm, regex, search_text)
}

fn do_search(vm: &VirtualMachine, regex: &Regex, search_text: String) -> PyResult {
match regex.find(&search_text) {
fn do_search(vm: &VirtualMachine, regex: &Regex, search_text: &str) -> PyResult {
match regex.find(search_text) {
None => Ok(vm.get_none()),
Some(result) => create_match(vm, &result),
}
Expand All @@ -98,19 +62,6 @@ fn make_regex(vm: &VirtualMachine, pattern: &str) -> PyResult<Regex> {
}
}

/// Inner data for a match object.
#[derive(Debug)]
struct PyMatch {
start: usize,
end: usize,
}

impl PyValue for PyMatch {
fn class(vm: &VirtualMachine) -> PyClassRef {
vm.class("re", "Match")
}
}

/// Take a found regular expression and convert it to proper match object.
fn create_match(vm: &VirtualMachine, match_value: &Match) -> PyResult {
// let mo = vm.invoke(match_class, PyFuncArgs::default())?;
Expand All @@ -124,68 +75,45 @@ fn create_match(vm: &VirtualMachine, match_value: &Match) -> PyResult {
.into_object())
}

/// Compile a regular expression into a Pattern object.
/// See also:
/// https://docs.python.org/3/library/re.html#re.compile
fn re_compile(pattern: PyStringRef, vm: &VirtualMachine) -> PyResult<PyRef<Regex>> {
let regex = make_regex(vm, &pattern.value)?;

Ok(regex.into_ref(vm))
fn re_compile(pattern: PyStringRef, vm: &VirtualMachine) -> PyResult<Regex> {
make_regex(vm, &pattern.value)
}

fn pattern_match(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(
vm,
args,
required = [(zelf, None), (text, Some(vm.ctx.str_type()))]
);

let regex = get_regex(zelf);
let search_text = objstr::get_value(text);
do_match(vm, &regex, search_text)
}

fn pattern_search(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(
vm,
args,
required = [(zelf, None), (text, Some(vm.ctx.str_type()))]
);

let regex = get_regex(zelf);
let search_text = objstr::get_value(text);
do_search(vm, &regex, search_text)
impl PyRegexRef {
fn match_(self, text: PyStringRef, vm: &VirtualMachine) -> PyResult {
do_match(vm, &self, &text.value)
}
fn search(self, text: PyStringRef, vm: &VirtualMachine) -> PyResult {
do_search(vm, &self, &text.value)
}
}

/// Returns start of match
/// see: https://docs.python.org/3/library/re.html#re.Match.start
fn match_start(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(vm, args, required = [(zelf, None)]);
// TODO: implement groups
let m = get_match(zelf);
Ok(vm.new_int(m.start))
impl PyMatchRef {
fn start(self, _vm: &VirtualMachine) -> usize {
self.start
}
fn end(self, _vm: &VirtualMachine) -> usize {
self.end
}
}

fn match_end(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(vm, args, required = [(zelf, None)]);
// TODO: implement groups
let m = get_match(zelf);
Ok(vm.new_int(m.end))
}
/// Create the python `re` module with all its members.
pub fn make_module(ctx: &PyContext) -> PyObjectRef {
let match_type = py_class!(ctx, "Match", ctx.object(), {
"start" => ctx.new_rustfunc(PyMatchRef::start),
"end" => ctx.new_rustfunc(PyMatchRef::end)
});

/// Retrieve inner rust regex from python object:
fn get_regex(obj: &PyObjectRef) -> &Regex {
// TODO: Regex shouldn't be stored in payload directly, create newtype wrapper
if let Some(regex) = obj.payload::<Regex>() {
return regex;
}
panic!("Inner error getting regex {:?}", obj);
}
let pattern_type = py_class!(ctx, "Pattern", ctx.object(), {
"match" => ctx.new_rustfunc(PyRegexRef::match_),
"search" => ctx.new_rustfunc(PyRegexRef::search)
});

/// Retrieve inner rust match from python object:
fn get_match(obj: &PyObjectRef) -> &PyMatch {
if let Some(value) = obj.payload::<PyMatch>() {
return value;
}
panic!("Inner error getting match {:?}", obj);
py_module!(ctx, "re", {
"compile" => ctx.new_rustfunc(re_compile),
"Match" => match_type,
"match" => ctx.new_rustfunc(re_match),
"Pattern" => pattern_type,
"search" => ctx.new_rustfunc(re_search)
})
}