inline dbg

This commit is contained in:
Folkert 2022-11-23 21:23:28 +01:00
parent dcb530d3af
commit e7f3c6f281
No known key found for this signature in database
GPG key ID: 1F17F6FFD112B97C
18 changed files with 192 additions and 21 deletions

View file

@ -939,7 +939,11 @@ fn roc_dev_native(
expect_metadata: ExpectMetadata,
) -> ! {
use roc_repl_expect::run::ExpectMemory;
use signal_hook::{consts::signal::SIGCHLD, consts::signal::SIGUSR1, iterator::Signals};
use signal_hook::{
consts::signal::SIGCHLD,
consts::signal::{SIGUSR1, SIGUSR2},
iterator::Signals,
};
let ExpectMetadata {
mut expectations,
@ -947,7 +951,7 @@ fn roc_dev_native(
layout_interner,
} = expect_metadata;
let mut signals = Signals::new(&[SIGCHLD, SIGUSR1]).unwrap();
let mut signals = Signals::new(&[SIGCHLD, SIGUSR1, SIGUSR2]).unwrap();
// let shm_name =
let shm_name = format!("/roc_expect_buffer_{}", std::process::id());
@ -993,6 +997,11 @@ fn roc_dev_native(
)
.unwrap();
}
SIGUSR2 => {
// this is the signal we use for a dbg
println!("I need to dbg something");
}
_ => println!("received signal {}", sig),
}
}

View file

@ -2,6 +2,7 @@ const std = @import("std");
const builtin = @import("builtin");
const SIGUSR1: c_int = if (builtin.os.tag.isDarwin()) 30 else 10;
const SIGUSR2: c_int = if (builtin.os.tag.isDarwin()) 31 else 12;
const O_RDWR: c_int = 2;
const O_CREAT: c_int = 64;
@ -87,3 +88,11 @@ pub fn expectFailedFinalize() callconv(.C) void {
_ = roc_send_signal(parent_pid, SIGUSR1);
}
}
pub fn sendDbg() callconv(.C) void {
if (builtin.os.tag == .macos or builtin.os.tag == .linux) {
const parent_pid = roc_getppid();
_ = roc_send_signal(parent_pid, SIGUSR2);
}
}

View file

@ -172,6 +172,7 @@ comptime {
exportUtilsFn(expect.expectFailedStartSharedBuffer, "expect_failed_start_shared_buffer");
exportUtilsFn(expect.expectFailedStartSharedFile, "expect_failed_start_shared_file");
exportUtilsFn(expect.expectFailedFinalize, "expect_failed_finalize");
exportUtilsFn(expect.sendDbg, "send_dbg");
// sets the buffer used for expect failures
@export(expect.setSharedBuffer, .{ .name = "set_shared_buffer", .linkage = .Weak });

View file

@ -410,6 +410,7 @@ pub const UTILS_EXPECT_FAILED_START_SHARED_FILE: &str =
"roc_builtins.utils.expect_failed_start_shared_file";
pub const UTILS_EXPECT_FAILED_FINALIZE: &str = "roc_builtins.utils.expect_failed_finalize";
pub const UTILS_EXPECT_READ_ENV_SHARED_BUFFER: &str = "roc_builtins.utils.read_env_shared_buffer";
pub const UTILS_SEND_DBG: &str = "roc_builtins.utils.send_dbg";
pub const UTILS_LONGJMP: &str = "longjmp";
pub const UTILS_SETJMP: &str = "setjmp";

View file

@ -87,6 +87,7 @@ macro_rules! map_symbol_to_lowlevel_and_arity {
LowLevel::PtrCast => unimplemented!(),
LowLevel::RefCountInc => unimplemented!(),
LowLevel::RefCountDec => unimplemented!(),
LowLevel::Dbg => unimplemented!(),
// these are not implemented, not sure why
LowLevel::StrFromInt => unimplemented!(),

View file

@ -611,6 +611,16 @@ fn deep_copy_expr_help<C: CopyEnv>(env: &mut C, copied: &mut Vec<Variable>, expr
lookups_in_cond: lookups_in_cond.to_vec(),
},
Dbg {
loc_condition,
loc_continuation,
variable,
} => Dbg {
loc_condition: Box::new(loc_condition.map(|e| go_help!(e))),
loc_continuation: Box::new(loc_continuation.map(|e| go_help!(e))),
variable: sub!(*variable),
},
TypedHole(v) => TypedHole(sub!(*v)),
RuntimeError(err) => RuntimeError(err.clone()),

View file

@ -240,6 +240,12 @@ pub enum Expr {
lookups_in_cond: Vec<ExpectLookup>,
},
Dbg {
loc_condition: Box<Loc<Expr>>,
loc_continuation: Box<Loc<Expr>>,
variable: Variable,
},
/// Rendered as empty box in editor
TypedHole(Variable),
@ -295,6 +301,8 @@ impl Expr {
Self::Expect { .. } => Category::Expect,
Self::ExpectFx { .. } => Category::Expect,
Self::Dbg { .. } => Category::Expect,
// these nodes place no constraints on the expression's type
Self::TypedHole(_) | Self::RuntimeError(..) => Category::Unknown,
}
@ -1826,6 +1834,28 @@ pub fn inline_calls(var_store: &mut VarStore, expr: Expr) -> Expr {
}
}
Dbg {
loc_condition,
loc_continuation,
variable,
} => {
let loc_condition = Loc {
region: loc_condition.region,
value: inline_calls(var_store, loc_condition.value),
};
let loc_continuation = Loc {
region: loc_continuation.region,
value: inline_calls(var_store, loc_continuation.value),
};
Dbg {
loc_condition: Box::new(loc_condition),
loc_continuation: Box::new(loc_continuation),
variable,
}
}
LetRec(defs, loc_expr, mark) => {
let mut new_defs = Vec::with_capacity(defs.len());
@ -2740,6 +2770,9 @@ fn get_lookup_symbols(expr: &Expr) -> Vec<ExpectLookup> {
}
| Expr::ExpectFx {
loc_continuation, ..
}
| Expr::Dbg {
loc_continuation, ..
} => {
stack.push(&loc_continuation.value);

View file

@ -952,24 +952,17 @@ fn fix_values_captured_in_closure_expr(
Expect {
loc_condition,
loc_continuation,
lookups_in_cond: _,
} => {
fix_values_captured_in_closure_expr(
&mut loc_condition.value,
no_capture_symbols,
closure_captures,
);
fix_values_captured_in_closure_expr(
&mut loc_continuation.value,
no_capture_symbols,
closure_captures,
);
..
}
ExpectFx {
| ExpectFx {
loc_condition,
loc_continuation,
lookups_in_cond: _,
..
}
| Dbg {
loc_condition,
loc_continuation,
..
} => {
fix_values_captured_in_closure_expr(
&mut loc_condition.value,

View file

@ -268,8 +268,7 @@ pub fn walk_expr<V: Visitor>(visitor: &mut V, expr: &Expr, var: Variable) {
loc_continuation,
lookups_in_cond: _,
} => {
// TODO: what type does an expect have? bool
visitor.visit_expr(&loc_condition.value, loc_condition.region, Variable::NULL);
visitor.visit_expr(&loc_condition.value, loc_condition.region, Variable::BOOL);
visitor.visit_expr(
&loc_continuation.value,
loc_continuation.region,
@ -281,8 +280,19 @@ pub fn walk_expr<V: Visitor>(visitor: &mut V, expr: &Expr, var: Variable) {
loc_continuation,
lookups_in_cond: _,
} => {
// TODO: what type does an expect have? bool
visitor.visit_expr(&loc_condition.value, loc_condition.region, Variable::NULL);
visitor.visit_expr(&loc_condition.value, loc_condition.region, Variable::BOOL);
visitor.visit_expr(
&loc_continuation.value,
loc_continuation.region,
Variable::NULL,
);
}
Expr::Dbg {
variable,
loc_condition,
loc_continuation,
} => {
visitor.visit_expr(&loc_condition.value, loc_condition.region, *variable);
visitor.visit_expr(
&loc_continuation.value,
loc_continuation.region,

View file

@ -656,6 +656,35 @@ pub fn constrain_expr(
constraints.exists_many(vars, all_constraints)
}
Dbg {
loc_condition,
loc_continuation,
variable,
} => {
let dbg_type = constraints.push_variable(*variable);
let expected_dbg = constraints.push_expected_type(Expected::NoExpectation(dbg_type));
let cond_con = constrain_expr(
types,
constraints,
env,
loc_condition.region,
&loc_condition.value,
expected_dbg,
);
let continuation_con = constrain_expr(
types,
constraints,
env,
loc_continuation.region,
&loc_continuation.value,
expected,
);
constraints.exists_many([], [cond_con, continuation_con])
}
If {
cond_var,
branch_var,

View file

@ -104,6 +104,13 @@ pub(crate) fn finalize(env: &Env) {
.build_call(func, &[], "call_expect_failed_finalize");
}
pub(crate) fn send_dbg(env: &Env) {
let func = env.module.get_function(bitcode::UTILS_SEND_DBG).unwrap();
env.builder
.build_call(func, &[], "call_expect_failed_finalize");
}
pub(crate) fn clone_to_shared_memory<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
scope: &Scope<'a, 'ctx>,

View file

@ -1119,6 +1119,25 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
ptr.into()
}
},
Dbg => {
// now what
arguments!(condition);
let region = roc_region::all::Region::zero(); // todo
crate::llvm::expect::clone_to_shared_memory(
env,
scope,
layout_ids,
args[0],
region,
&[],
);
crate::llvm::expect::send_dbg(env);
condition
}
}
}

View file

@ -1874,6 +1874,8 @@ impl<'a> LowLevelCall<'a> {
},
StoredValue::StackMemory { .. } => { /* do nothing */ }
},
Dbg => todo!("{:?}", self.lowlevel),
}
}

View file

@ -112,6 +112,7 @@ pub enum LowLevel {
RefCountDec,
BoxExpr,
UnboxExpr,
Dbg,
Unreachable,
}
@ -208,11 +209,13 @@ macro_rules! map_symbol_to_lowlevel {
LowLevel::NumToIntChecked => unreachable!(),
LowLevel::NumToFloatChecked => unreachable!(),
// these are used internally and not tied to a symbol
LowLevel::Hash => unimplemented!(),
LowLevel::PtrCast => unimplemented!(),
LowLevel::RefCountInc => unimplemented!(),
LowLevel::RefCountDec => unimplemented!(),
LowLevel::Dbg => unreachable!(),
// these are not implemented, not sure why
LowLevel::StrFromInt => unimplemented!(),

View file

@ -937,6 +937,8 @@ pub fn lowlevel_borrow_signature(arena: &Bump, op: LowLevel) -> &[bool] {
ListIsUnique => arena.alloc_slice_copy(&[borrowed]),
Dbg => arena.alloc_slice_copy(&[borrowed]),
BoxExpr | UnboxExpr => {
unreachable!("These lowlevel operations are turned into mono Expr's")
}

View file

@ -4403,6 +4403,7 @@ pub fn with_hole<'a>(
Expect { .. } => unreachable!("I think this is unreachable"),
ExpectFx { .. } => unreachable!("I think this is unreachable"),
Dbg { .. } => unreachable!("I think this is unreachable"),
If {
cond_var,
@ -6546,6 +6547,42 @@ pub fn from_can<'a>(
stmt
}
Dbg {
loc_condition,
loc_continuation,
variable,
} => {
let rest = from_can(env, variable, loc_continuation.value, procs, layout_cache);
let dbg_symbol = env.unique_symbol();
let call = crate::ir::Call {
call_type: CallType::LowLevel {
op: LowLevel::Dbg,
update_mode: env.next_update_mode_id(),
},
arguments: env.arena.alloc([dbg_symbol]),
};
let dbg_layout = layout_cache
.from_var(env.arena, variable, env.subs)
.expect("invalid dbg_layout");
let expr = Expr::Call(call);
let mut stmt = Stmt::Let(dbg_symbol, expr, dbg_layout, env.arena.alloc(rest));
stmt = with_hole(
env,
loc_condition.value,
variable,
procs,
layout_cache,
dbg_symbol,
env.arena.alloc(stmt),
);
stmt
}
LetRec(defs, cont, _cycle_mark) => {
// because Roc is strict, only functions can be recursive!
for def in defs.into_iter() {

View file

@ -3529,6 +3529,7 @@ pub enum Category {
AbilityMemberSpecialization(Symbol),
Expect,
Dbg,
Unknown,
}

View file

@ -1696,6 +1696,10 @@ fn format_category<'b>(
alloc.concat([this_is, alloc.text(" an expectation")]),
alloc.text(" of type:"),
),
Dbg => (
alloc.concat([this_is, alloc.text(" a dbg statement")]),
alloc.text(" of type:"),
),
}
}