myst-lang / myst

A structured, dynamic, general-purpose language.
http://myst-lang.org
MIT License
119 stars 17 forks source link

Standard library entries to match Getting Started guide #57

Closed faultyserver closed 6 years ago

faultyserver commented 7 years ago

This issue has been marked as a "Good First Issue"! If you'd like to tackle this issue as your first contribution to the project, be sure to read the Get Involved section of the README for some help with how to get started.

This is also a very large issue with many parts. It is meant to be tackled piece-by-piece. A contribution that implements even one of these methods will gladly be accepted.

For the past few weeks, I've been working on a Getting Started guide for Myst. In that guide, I make some references to standard library functions that don't actually exist yet. The goal of this issue is to list all of the functions that are referenced that do not yet have an implementation so that they can be added one by one. Since the guide is not finished, entries may be added to this issue in the future.

Additionally, there are some other functions that I think would be good additions for the next release.

Some of these functions will be part of the native library (written in Crystal), while others will be part of the standard library (written in Myst). Each entry here has a small description of what it should do. For the most part, these follow the versions from Ruby, so feel free to look there for inspiration.

Native library

Standard library

Implementation

Obviously, there are a lot of things to add. I don't expect that all of these would be added in a single PR. Tackling them one at a time is fine by me.

Adding functions to the native library can be done in the src/myst/interpreter/native_lib folder. All of the types listed above should already exist there. Use NativeLib.method to write the implementation for a function, then call NativeLib.def_instance_method or NativeLib.def_method to add it to the appropriate module. There are plenty of examples in the code already that should help you out.

The standard library exists in the stdlib folder at the top level. Look at the existing entries (specifically, Enumerable) to see how new functions can be added.

Also, please try to add a descriptive comment to each method describing the arguments that it accepts, the values that might be returned and a description of what the method does. The Enumerable module) has some good examples of these comments.

If you'd like to pick up one or more of these functions, please comment below saying which function you would like to implement so that others know they are taken.

As always, if you have any other questions, feel free to ask them here or let me know directly so I can help out :) Good luck!

faultyserver commented 6 years ago

To expand a bit on how native library methods can be added:

The interpreter provides a few helper macros under the NativeLib module, namely method, def_method, and def_instance_method. These end up getting used by files in the native_lib folder to create and register methods on types in the Kernel.

Adding a new method to the native library is a two-step process:

  1. use NativeLib.method to define the method implementation. For example, the String#size implementation looks like this: https://github.com/myst-lang/myst/blob/aea25887f8bde444351f5590c69a11f256d61a4d/src/myst/interpreter/native_lib/string.cr#L56-L58 The first argument to this function is the name of the implementation. This is often made up of the name of the type the method is being defined on, followed by the name of the method being implemented. The second argument is the type to use for the self object (available as the variable this) while inside the method.   Any further arguments are parameters for the method, and require a type restriction (normally just Value). The other methods in native_lib/string.cr show this usage.

  2. In the init_* method for the type (e.g., init_string in native_lib/string.cr), use NativeLib.def_instance_method to register the implementation with the type it belongs to. For example, the String#size method shown above is registered with a line like this:

    NativeLib.def_instance_method(string_type, :size,   :string_size)

    Here, string_type is the Type that represents String in Myst (see it's instantiation at the beginning of init_string). :size is the name of the method as it should appear in Myst, and string_size is the name of the implementation method.

def_instance_method is used to define instance methods for Types. It will register the method in the instance_scope of the given TType. def_method is used to define static methods, or methods for Modules (e.g., IO.puts). The arguments for the two use the same structure.

Hopefully that helps clear up how the Native Library is built up. Feel free to ask any more questions in the #help channel in the discord, or on here.

faultyserver commented 6 years ago

I've removed the Dir.[pattern : String] method from this issue because it doesn't really fit any of the other things here. Without more methods on Dir and File, it's pretty useless anyway.

For reference, here is the original text:

With that, this issue is complete! Thank you to everyone who helped implement these methods! This has been a long-lived issue, but 0.3.0 will be a great release because of it :) Thanks again.