Skip to content
This repository has been archived by the owner on Jun 3, 2021. It is now read-only.

[WIP] Add a proper REPL #464

Closed
wants to merge 8 commits into from
Closed

[WIP] Add a proper REPL #464

wants to merge 8 commits into from

Conversation

Stupremee
Copy link
Contributor

@Stupremee Stupremee commented Jun 2, 2020

This PR will introduce a proper Repl using rustyline and the jit backend.
My current plan is to have a buffer which holds the code.
Every line will be processed like this:

  • append code to code buffer
  • check semantics of buffer
  • if new code contains main method, execute it and reset the buffer
  • otherwise just add the code to the buffer

It's probably possible to not reset the buffer and just override the main method in the existing program.
I'n also thinking about making the buffer not a string, but a list of parsed statements.

Resolves #372

src/lib.rs Outdated Show resolved Hide resolved
Cargo.toml Outdated Show resolved Hide resolved
Comment on lines 22 to 29
fn complete(
&self,
_line: &str,
_pos: usize,
_ctx: &Context<'_>,
) -> Result<(usize, Vec<Pair>), ReadlineError> {
Ok((0, vec![]))
}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd love to do lots of fancy things with tab-completion, but that's a larger project, no need for it in a first draft.

src/repl/helper.rs Outdated Show resolved Hide resolved
src/repl/mod.rs Outdated Show resolved Hide resolved
src/repl/mod.rs Outdated Show resolved Hide resolved
@jyn514
Copy link
Owner

jyn514 commented Jun 3, 2020

if new code contains main method, execute it and reset the buffer, otherwise just add the code to the buffer

I'd actually like to evaluate things as expressions by default, not as declarations. This is how node behaves:

> 1 + 2
3

and also GHCI and python

Prelude> 1 + 2
3
>>> 1 + 2
3

You can parse things as expressions by creating a new Analyzer and calling .expr(). This would be easiest by using the analyze function in src/analyze/mod.rs - it's currently test-only, but I think it's fine to make it usable in all contexts.

@Stupremee
Copy link
Contributor Author

But how should the result of the expression then be calculated? We do not have an interpreter, only a jit and I have no idea how we can get the result of the jitted code that gets executed.

Stupremee added 5 commits June 6, 2020 23:53
- Hide repl behind a feature gate
- Create basic command module
- Start repl automatically if no input is provided
- Move all methods from swcc module to a common module
- Add swcci binary
Comment on lines 68 to 71
pub(super) const USAGE: &str = "\
usage: swcc [--help | -h] [--version | -V] [--debug-ir] [--debug-ast] [--debug-lex]
[--debug-hir] [--jit] [--no-link | -c] [--preprocess-only | -E]
[-I <dir>] [-D <id[=val]>] [<file>]";
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it makes sense to share this across both binaries.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I realized that after I committed it 😅
It will be fixed asap.

- backtrace mod and ColorChoice are now in common mod
- Add some first code checking stuff to repl execute_code
- entered expression is inserted in the return expression of the main
function
- result of the "program" is printed to stdout
@@ -1052,6 +1052,7 @@ impl PureAnalyzer {
/// This returns an opaque index to the `Metadata`.
fn declare(&mut self, mut decl: Variable, init: bool, location: Location) -> Symbol {
if decl.id == "main".into() {
println!("main: {:?}", decl);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
println!("main: {:?}", decl);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ups 😅

Comment on lines +101 to +139
let expr = match analyze(code, Parser::expr, PureAnalyzer::expr) {
Ok(mut expr) => {
expr.ctype = types::Type::Int(true);
expr
}
Err(err) => {
println!("error: {}", err.data);
return;
}
};
let function_type = types::FunctionType {
return_type: Box::new(types::Type::Int(true)),
params: vec![],
varargs: false,
};
let qualifiers = hir::Qualifiers {
volatile: false,
c_const: false,
func: hir::FunctionQualifiers {
inline: false,
no_return: false,
},
};

let main = hir::Variable {
ctype: types::Type::Function(function_type),
storage_class: data::StorageClass::Extern,
qualifiers,
id: saltwater::InternedStr::get_or_intern("main"),
};

let span = expr.location;
let stmt = span.with(hir::StmtType::Return(Some(expr)));
let init = hir::Initializer::FunctionBody(vec![stmt]);
let decl = hir::Declaration {
symbol: main.insert(),
init: Some(init),
};
let (result, _warns) = ir::compile(module, vec![span.with(decl)], false);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks useful on its own, can you make it a function in src/lib.rs called eval() that's implemented on JIT?

ctype: types::Type::Function(function_type),
storage_class: data::StorageClass::Extern,
qualifiers,
id: saltwater::InternedStr::get_or_intern("main"),
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
id: saltwater::InternedStr::get_or_intern("main"),
id: "main".into(),

Comment on lines +116 to +123
let qualifiers = hir::Qualifiers {
volatile: false,
c_const: false,
func: hir::FunctionQualifiers {
inline: false,
no_return: false,
},
};
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let qualifiers = hir::Qualifiers {
volatile: false,
c_const: false,
func: hir::FunctionQualifiers {
inline: false,
no_return: false,
},
};
let qualifiers = hir::Qualifiers::default();

let module = initialize_jit_module();
let expr = match analyze(code, Parser::expr, PureAnalyzer::expr) {
Ok(mut expr) => {
expr.ctype = types::Type::Int(true);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't look right. What's this meant to do?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this crashes on strings:

>> "a"
The application panicked (crashed).
Message:  verification error: - inst1 (return v0): arg 0 (v0) has type i64, must match function signature of i32

note: while compiling function u0:0() -> i32 system_v {
    gv0 = symbol colocated u1:0

block0:
    v0 = global_value.i64 gv0
    return v0
}

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead you could use a function name other than main and set the return type to the type of the expression. Then you decide how to display the result depending on the type. That would also fix the current bug where 'a' is displayed as 99.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good idea

Copy link
Contributor Author

@Stupremee Stupremee Jun 14, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had this code there, because otherwise I got an error from cranelift that it expected an i32 but got i64.

verification error: - inst1 (return v0): arg 0 (v0) has type i64, must match function signature of i32

note: while compiling function u0:0() -> i32 system_v {
block0:
    v0 = iconst.i64 1
    return v0
}

Comment on lines +141 to +146
if let Err(err) = result {
println!("failed to compile: {}", err.data);
return;
}

let module = result.unwrap();
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try to avoid unwrap if possible.

Suggested change
if let Err(err) = result {
println!("failed to compile: {}", err.data);
return;
}
let module = result.unwrap();
let module = match result {
Err(err) => {
println!("failed to compile: {}", err.data);
return;
}
Ok(module) => module),
};

@Stupremee
Copy link
Contributor Author

I will close this pull request and reopen one because I have lost the overview and am not really satisfied with this one.

@Stupremee Stupremee closed this Jul 24, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Use rustyline for REPL
2 participants