Skip to content
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

implemented bitwise operators #266

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
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
142 changes: 118 additions & 24 deletions compiler/src/builtins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ impl Value {
}
_ => (),
},
Value::Macro(m) => match member.as_ref().as_str() {
Value::Macro(Macro::FuncLike(m)) => match member.as_ref().as_str() {
"args" => {
let mut args = vec![];
for MacroArgDef {
Expand Down Expand Up @@ -297,7 +297,7 @@ impl Value {
Value::Builtins => match Builtin::from_str(member.as_str()) {
Err(_) => None,
Ok(builtin) => Some(store_const_value(
Value::BuiltinFunction(builtin),
Value::Macro(Macro::BuiltinLike(builtin)),
globals,
context.start_group,
info.position,
Expand Down Expand Up @@ -508,6 +508,32 @@ macro_rules! builtins {
Self::new()
}
}


pub fn get_builtin_arg_patterns(b: &Builtin) -> Option<Vec<Pattern>> {
match b {
$(
Builtin::$variant => {
$( if stringify!($argdesc) == "any" { return None } )?
$( if stringify!($argdesc) == "none" { return Some(vec![]) } )?

$(
return Some(vec![$(
loop {
$( break pattern_from_value_variant(stringify!($arg_type)); )?
#[allow(unreachable_code)]
break Pattern::Any
},
)+]);
)?

#[allow(unreachable_code)]
None
}
)*
}
}

#[inline]
pub fn built_in_function(
func: Builtin,
Expand Down Expand Up @@ -1946,6 +1972,38 @@ $.assert(name_age == {
}
}

[Call] #[safe = true, desc = "Calls a macro with the arguments provided in an array", example = "
m = (x, y) => x + y
$.assert($.call(m, [1, 2]) == 3)
"]
fn call((m): Macro, (args): Array) {

if let Macro::FuncLike(m) = m {
let args = args.iter()
.map(|s| parser::ast::Argument::from(*s, globals.stored_values.map.get(*s).unwrap().def_area.pos) )
.collect::<Vec<parser::ast::Argument>>();


let full_context = unsafe { FullContext::from_ptr(full_context) };
let parent = full_context.inner().return_value2;
execute_macro(
(m, args.clone()),
full_context,
globals,
parent,
info.clone(),
)?;
globals.stored_values[full_context.inner().return_value].clone()
} else {
return Err(RuntimeError::BuiltinError {
builtin,
message: format!("Can only dynamically call func-like macros (so far)"),
info,
})
}

}

[Regex] #[safe = true, desc = "Performs a regex operation on a string", example = ""]
fn regex(#["`mode` can be either \"match\", \"replace\", \"find_all\" or \"find_groups\""](regex): Str, (s): Str, (mode): Str, (replace)) {
use fancy_regex::Regex;
Expand Down Expand Up @@ -2329,6 +2387,22 @@ $.assert(name_age == {
(*globals.stored_values.map.get_mut(arguments[0]).unwrap()).def_area = info.position;
Value::Null
}
[RightShiftOp] #[safe = true, desc = "Default implementation of the `>>` operator", example = "$._right_shift_(10, 2)"]
fn _right_shift_((a): Number, (b): Number) {
Value::Number(((a as i128) >> (b as i128)) as f64)
}
[LeftShiftOp] #[safe = true, desc = "Default implementation of the `<<` operator", example = "$._left_shift_(3, 1)"]
fn _left_shift_((a): Number, (b): Number) {
Value::Number(((a as i128) << (b as i128)) as f64)
}
[BitNotOp] #[safe = true, desc = "Default implementation of the `~n` operator", example = "$._bit_not_(4)"]
fn _bit_not_((a): Number) {
Value::Number((!(a as i128)) as f64)
}
[BitXorOp] #[safe = true, desc = "Default implementation of the `~?` operator", example = "$._bit_xor_(4, 9)"]
fn _bit_xor_((a): Number, (b): Number) {
Value::Number(((a as i128) ^ (b as i128)) as f64)
}
[SwapOp] #[safe = true, desc = "Default implementation of the `<=>` operator", example = "let a = 10\nlet b = 5\n$._swap_(a, b)\n$.assert(a == 5)\n$.assert(b == 10)"]
fn _swap_(mut (a), mut (b)) {

Expand Down Expand Up @@ -2563,36 +2637,56 @@ $.assert(name_age == {
Value::Null
}

[LeftShiftAssignOp] #[safe = true, desc = "Default implementation of the `<<=` operator", example = "let val = 8\n$._left_shift_assign_(val, 5)\n$.assert(val == 256)"]
fn _left_shift_assign_(mut (a): Number, (b): Number) {a = ((a as i128) << (b as i128)) as f64; Value::Null}

[RightShiftAssignOp] #[safe = true, desc = "Default implementation of the `>>=` operator", example = "let val = 32\n$._right_shift_assign_(val, 2)\n$.assert(val == 8)"]
fn _right_shift_assign_(mut (a): Number, (b): Number) {a = ((a as i128) >> (b as i128)) as f64; Value::Null}

[EitherOp] #[safe = true, desc = "Default implementation of the `|` operator", example = "$._either_(@number, @counter)"]
fn _either_((a), (b)) {
Value::Pattern(Pattern::Either(
if let Value::Pattern(p) = convert_type(&a, type_id!(pattern), &info, globals, context)? {
Box::new(p)
} else {
unreachable!()
},
if let Value::Pattern(p) = convert_type(&b, type_id!(pattern), &info, globals, context)? {
Box::new(p)
} else {
unreachable!()
match (a.clone(), b.clone()) {
(Value::Number(a), Value::Number(b)) => {
Value::Number(((a as i128) | (b as i128)) as f64)
},
))
_ => {
Value::Pattern(Pattern::Either(
if let Value::Pattern(p) = convert_type(&a, type_id!(pattern), &info, globals, context)? {
Box::new(p)
} else {
unreachable!()
},
if let Value::Pattern(p) = convert_type(&b, type_id!(pattern), &info, globals, context)? {
Box::new(p)
} else {
unreachable!()
},
))
}
}
}

[BothOp] #[safe = true, desc = "Default implementation of the `&` operator", example = "$._both_(@number, @counter)"]
fn _both_((a), (b)) {
Value::Pattern(Pattern::Both(
if let Value::Pattern(p) = convert_type(&a, type_id!(pattern), &info, globals, context)? {
Box::new(p)
} else {
unreachable!()
},
if let Value::Pattern(p) = convert_type(&b, type_id!(pattern), &info, globals, context)? {
Box::new(p)
} else {
unreachable!()
match (a.clone(), b.clone()) {
(Value::Number(a), Value::Number(b)) => {
Value::Number(((a as i128) & (b as i128)) as f64)
},
))
_ => {
Value::Pattern(Pattern::Both(
if let Value::Pattern(p) = convert_type(&a, type_id!(pattern), &info, globals, context)? {
Box::new(p)
} else {
unreachable!()
},
if let Value::Pattern(p) = convert_type(&b, type_id!(pattern), &info, globals, context)? {
Box::new(p)
} else {
unreachable!()
},
))
}
}
}

[DisplayOp] #[safe = true, desc = "returns the default value display string for the given value", example = "$._display_(counter()) // \"@counter::{ item: ?i, bits: 16 }\""] fn _display_((a)) {
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ pub fn compile_scope(
Value::Builtins => {
for name in BUILTIN_LIST.iter() {
let p = store_const_value(
Value::BuiltinFunction(*name),
Value::Macro(Macro::BuiltinLike(*name)),
globals,
fn_context,
info.position,
Expand Down
15 changes: 10 additions & 5 deletions compiler/src/compiler_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ pub fn handle_operator(
globals,
info.clone(),
) {
if let Value::Macro(m) = globals.stored_values[val].clone() {
if let Value::Macro(Macro::FuncLike(m)) = globals.stored_values[val].clone() {
if m.args.is_empty() {
return Err(RuntimeError::CustomError(create_error(
info.clone(),
Expand Down Expand Up @@ -91,7 +91,7 @@ pub fn handle_operator(

execute_macro(
(
*m,
m,
//copies argument so the original value can't be mutated
//prevents side effects and shit
vec![ast::Argument::from(
Expand Down Expand Up @@ -142,7 +142,7 @@ pub fn handle_unary_operator(
globals,
info.clone(),
) {
if let Value::Macro(m) = globals.stored_values[val].clone() {
if let Value::Macro(Macro::FuncLike(m)) = globals.stored_values[val].clone() {
if m.args.is_empty() {
return Err(RuntimeError::CustomError(create_error(
info.clone(),
Expand All @@ -152,7 +152,7 @@ pub fn handle_unary_operator(
)));
}

execute_macro((*m, Vec::new()), full_context, globals, value, info.clone())?;
execute_macro((m, Vec::new()), full_context, globals, value, info.clone())?;
} else {
built_in_function(macro_name, vec![value], info.clone(), globals, full_context)?;
}
Expand Down Expand Up @@ -227,6 +227,11 @@ impl From<ast::Operator> for Builtin {
Divide => DivideOp,
IntDivide => IntdivideOp,
Is => IsOp,
RightShift => RightShiftOp,
LeftShift => LeftShiftOp,
BitXor => BitXorOp,
LeftShiftAssign => LeftShiftAssignOp,
RightShiftAssign => RightShiftAssignOp
}
}
}
Expand Down Expand Up @@ -311,7 +316,7 @@ impl EvalExpression for ast::Expression {
}

pub fn execute_macro(
(m, args): (Macro, Vec<ast::Argument>),
(m, args): (MacroFuncData, Vec<ast::Argument>),
contexts: &mut FullContext,
globals: &mut Globals,
parent: StoredValue,
Expand Down
Loading