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

repl for zig #596

Closed
pluto439 opened this issue Nov 7, 2017 · 13 comments
Closed

repl for zig #596

pluto439 opened this issue Nov 7, 2017 · 13 comments
Labels
accepted This proposal is planned. proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.
Milestone

Comments

@pluto439
Copy link

pluto439 commented Nov 7, 2017

Having read eval print loop for zig would've been cool. I'd be able to make zig programs in the same way I made python programs: by copypasting code into console and getting feedback immediately, but I would still be able compile and distribute it as a binary program.

hot code swapping #68 is somewhat related, but it's more about editing existing functions. It's much simplier to implement.

The best way to archive this is to copy python and lisp (and maybe smalltalk), they are the prime examples of languages that work like that. They can be programmed by editing your program without stopping to recompile anything. Maybe there's something to learn from shells too, I'm not good at them. I like how you can make labels in bash and use goto.

One thing about python is that using functions in there is completely optional. You can just type code directly, and create variables directly, they will end up as global variables. In an enviroment like that, being able to delete variables is important, because they will never be deleted overwise. See issue #594, deleting a variable mid function.

Getting rid of defer is also important because of that. It only fires at the end of function, which is never in this scenario. I'd get rid of it anyway, because I prefer error handling through goto, I sometimes need for defer to execute somewhere mid function.

Need to make some support of object versioning (or structure versioning, whatever) to be able to modify structures at runtime. The way I see it, is that if you need to change something in some_structure, you create some_structure_2, convert every some_structure into some_structure_2, and then rename structure declarations. If there are not too many instances of some_structure, maybe it could be done automatically.

Optional: one thing that annoyed me about python, is that I can't save result from function call easily. I type do_something(), look at the result, see if it's what I need, go back to the beginning of the line, add res =, execute it again. I'd like for my code to be executed as I type. So that I type do, tooltip appears, I press tab, now I have do-something, it gets executed instantly, I see if everything went good, I add -- res at the end if I want to. It would be much more comfortable and fast. It's pretty much polish notation, I think it's a really good thing for programming languages to have, don't need to memorise operator precedence. Polish notation is more natural for computers, + - and or came from humans.

Optional: need to also minimize the need for declaring variable type ahead of time, make it behave like auto in c++ and everything python. The only place types should appear is in function declarations. This is what := in golang does. It's most likely impossible to archive completely, but at least to some degree, maybe. Creating scopes (code blocks) stands in a way of this auto, because then you have to create variables ahead of time. The only alternative to scopes is deleting every no longer needed variable manually, with del statement or something like that. Something like // after the variable. Once an ide is done, it will be possible to highlight the scope of a variable, all it's lifetime. Just creating code blocks may be more simple though, but I think deleting variables is more natural.

This is my dream language, it completely blurs the border between interpreted and compiled languages. I'm describing a completely different language from zig, ain't I? I'll probably have to do it myself. If you want to read some of my ramblings, here https://board.flatassembler.net/topic.php?t=20106

@thejoshwolfe
Copy link
Contributor

Zig behaves very much like an interpreted language with comptime code execution. For example, comptime var x = 0; is acceptable, but var x = 0; is a compile error; instead you need var x: i32 = 0; or the like.

Additionally the ++ operator only works at comptime.

One major missing feature is the ability to declare functions in the same syntactic context as imperative code. Top level scope in Zig is declarative and declaration order never matters. This means that if there were a zig repl, it would not be top level syntax. It might make more sense that what you type goes into an implicit main() function, but that doesn't quite work either. Functions cannot (currently) be declared in function scope, and that's related to Zig's lack of closures, and also tangled up with the concept of hidden allocations. see #229. I believe there is a way to work around this by declaring a local type and declaring methods there, like C++, but at this point we're far from the goal of a repl.

If there were a zig repl, the syntax would need to be special repl syntax that doesn't work anywhere in a zig source file. It might be neat for rapid development, but it wouldn't make as much sense for Zig as it does for top-level-imperative languages like Python.

@pluto439
Copy link
Author

pluto439 commented Nov 7, 2017

The "implicit main" idea is pretty nice. It's good to think about it as a main function that grows down as you type commands in repl.

I think it will be possible without closures. If you copypaste a function in repl, it will be declared as a new function, near the "implicit main". I even have an idea: once you called a function that doesn't exist, zig will offer you to create it, and you can autoexpand it just like you autoexpanded main before.

@Ilariel
Copy link

Ilariel commented Nov 7, 2017

I believe a repl-like environment would be nice for interactive testing. However there are many issues that have to solved first.

Here are some that come into my mind.

Nature of Zig

Zig is a relatively low level language at least at the moment. While we have some high level features, Zig is still quite close to C but it has compile time features for replacing build systems and the preprocessor.

Memory management

A repl is fundamentally a big global environment which you manipulate by adding and deleting variables and functions and you evaluate expressions in this environment.

How do you securely manage memory manually in this kind of environment?
Where does the memory come from?
What happens when you delete a pointer variable and don't deallocate the memory it pointed to?
What about stack memory?

Python, many lisp implementation and smalltalk are all garbage collected languages. They all implement some form of automatic memory management that Zig doesn't have.

Foreing function interface

For the repl to have any value, other than it mimicking the syntax of Zig, it would have to have to able to actually run real Zig code and that real Zig code probably wants to interface with the operating system and other libraries that are already compiled. Loading and unloading dynamic libraries at runtime should be possible.
Then there is the issue of managing resources that the OS possibly wants you to free after you are done with them like files, graphical elements like windows and other such resources.

Syntax issues

Would the repl have special syntax for behavior that doesn't exists in normal Zig or would the features of the repl be limited by Zig syntax?

@andrewrk
Copy link
Member

andrewrk commented Nov 7, 2017

I want to point out that you can load up a binary in gdb, and it's pretty darn close to a zig repl. You can call functions, allocate memory, do pretty much anything.

The other thing I want to point out is that we could have a zig repl that behaves like everything is in a giant comptime block. So certain things wouldn't be allowed, like syscalls, external function calls, and pointer reinterpreting.

...or maybe that's the difference between zig repl and normal comptime blocks, we hack up some stuff to let these operations work in the comptime environment, and it works well enough to be useful.

@pluto439
Copy link
Author

pluto439 commented Nov 7, 2017

I don't know how comptime and build system in zig works, so I can't comment on that. I want there to not be any language difference between programming in repl zig and programming in zig.

Memory management

garbage collection is absolutely not necessary in repl. Repl is just a bunch of text on input and a bunch of executable binary code on output. Practically, two arrays. I had something like repl in assembly, I changed code and executed it immediately.

Foreing function interface

Pretty easy, just need to provide correct headers.

I want to point out that you can load up a binary in gdb, and it's pretty darn close to a zig repl.

This. Except using gdb is a torture. Need to make a proper ide as soon as possible.

@pluto439
Copy link
Author

pluto439 commented Nov 9, 2017

About "Optional: need to also minimize the need for declaring variable type ahead of time", disregard this, it's impossible.

To take some variable outside of the for loop, the variable must be declared before entering the for loop.

Variable creation and variable deletion must be on the same level, in the same scope. Overwise it would require a really complex logic to figure out if a variable still exists after some for or not.

@andrewrk andrewrk added this to the 0.3.0 milestone Nov 22, 2017
@andrewrk andrewrk added the proposal This issue suggests modifications. If it also has the "accepted" label then it is planned. label Nov 22, 2017
@andrewrk andrewrk modified the milestones: 0.3.0, 0.4.0 Feb 28, 2018
@0joshuaolson1
Copy link

I want there to not be any language difference between programming in repl zig and programming in zig.

I'm not sure whether DRY should apply to zig's design for both a repl and a whole-program-optimized-with-compiler-flags module. Some copy semantics/other complex bugs caught at 'comptime' could be triggered by a line entered later. What do you do, retype all of the lines since then and time-travel-debug (maybe gdb does that, I dunno)? Maybe that's an issue for most repls in general...

And @andrewrk pointed out that comptime is too limiting for a repl as is. Maybe std's llvm compiler-as-a-service api can annotate which parts of the AST of the previous expression/statement/line are completely comptime and which are not, and JIT would run both without comptime's usual syscall restrictions? But how should Window's runtime getStdOut work?

To take some variable outside of the for loop, the variable must be declared before entering the for loop.

If that's inconvenient (assuming the repl/command line is line-based and can't 'scroll up'), the repl task might be better served by a real IDE/editor in a (compile-fast) edit-save-run loop.

Variable creation and variable deletion must be on the same level, in the same scope.

Since that's been rejected in the past, what if a special repltime library (or better yet, a reserved keyword) let you tell the compiler to pretend that a particular variable went out of scope ? I have no idea where in AST building/analysis that scopes are handled, so it may not be as simple as emulating a '}'.

@andrewrk andrewrk modified the milestones: 0.4.0, 0.5.0 Nov 21, 2018
@Hejsil
Copy link
Contributor

Hejsil commented Dec 18, 2018

I cooked up something simple: https://github.com/Hejsil/hacky-zig-repl
It's a little limited, but it's good for testing out simple things (this is not a solution to this issue, but something simple we can use for now).

@andrewrk andrewrk modified the milestones: 0.5.0, 0.6.0 Apr 30, 2019
@vegai
Copy link
Contributor

vegai commented Sep 17, 2019

Swift implements a REPL on top of LLDB. https://swift.org/lldb/

Perhaps that technique might work for Zig too? Although it looks like they manage this by maintaining a snowflake version of lldb: https://github.com/apple/swift-lldb

@andrewrk
Copy link
Member

andrewrk commented Oct 9, 2020

This is essentially implemented with the new --watch flag. There are plenty of missing REPL features to be implemented, and those can be separate issues.

@andrewrk andrewrk closed this as completed Oct 9, 2020
@andrewrk andrewrk added the accepted This proposal is planned. label Oct 9, 2020
@zcaudate
Copy link

zcaudate commented Oct 7, 2021

following up on this. is there a guide on how to use --watch?

If I just wanted to evaluate some copy and paste zig code from the net. what's the best way to evaluate it?

@pannous
Copy link

pannous commented Apr 17, 2022

please reopen

@nektro
Copy link
Contributor

nektro commented Apr 17, 2022

If I just wanted to evaluate some copy and paste zig code from the net. what's the best way to evaluate it?

offtopic, but https://zig.godbolt.org/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
accepted This proposal is planned. proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.
Projects
None yet
Development

No branches or pull requests

10 participants