Skip to content

Commit

Permalink
Towards a full-blown builtins DSL (part 3)
Browse files Browse the repository at this point in the history
WIP

Partially auto-generated, partially manually written builtins nodes for
File.
The next step is to auto-generate builtins craft using enhanced
annotation processor.
  • Loading branch information
hubertp committed May 23, 2022
1 parent 688df98 commit aec60a5
Show file tree
Hide file tree
Showing 26 changed files with 545 additions and 100 deletions.
3 changes: 2 additions & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -983,7 +983,8 @@ lazy val `interpreter-dsl` = (project in file("lib/scala/interpreter-dsl"))
frgaalJavaCompilerSetting,
libraryDependencies ++= Seq(
"org.apache.commons" % "commons-lang3" % commonsLangVersion,
"org.netbeans.api" % "org-openide-util-lookup" % "RELEASE130"
"org.netbeans.api" % "org-openide-util-lookup" % "RELEASE130",
"com.google.guava" % "guava" % guavaVersion exclude ("com.google.code.findbugs", "jsr305"),
)
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ type Project_Description

Enso_Project.root
root : File.File
root = File.new this.prim_root_file.getPath
root = File.new this.prim_root_file

## Returns the root data directory of the project.

Expand Down
91 changes: 47 additions & 44 deletions distribution/lib/Standard/Base/0.0.0-dev/src/System/File.enso
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,7 @@ polyglot java import java.nio.file.Path

example_new = File.new Examples.csv_path
new : (Text | File) -> File
new path = case path of
Text -> File (here.get_file path)
_ -> path
new path = @Builtin_Method "File.new"

## Open and reads all bytes in the file at the provided `path` into a byte vector.

Expand All @@ -52,7 +50,7 @@ read_bytes : (Text | File) -> Vector.Vector ! File_Error
read_bytes path =
file = case path of
Text -> (here.new path)
File _ -> path
File -> path
_ -> Error.throw (Illegal_Argument_Error "path should be either a File or a Text")
file.read_bytes

Expand Down Expand Up @@ -85,7 +83,7 @@ read_text : (Text | File) -> Encoding -> Problem_Behavior -> Text
read_text path (encoding=Encoding.utf_8) (on_problems=Report_Warning) =
file = case path of
Text -> (here.new path)
File _ -> path
File -> path
_ -> Error.throw (Illegal_Argument_Error "path should be either a File or a Text")
file.read_text encoding on_problems

Expand Down Expand Up @@ -115,7 +113,7 @@ write_text : (Text | File) -> Text -> Encoding -> Text
write_text path contents (encoding=Encoding.utf_8) =
file = case path of
Text -> (here.new path)
File _ -> path
File -> path
_ -> Error.throw (Illegal_Argument_Error "path should be either a File or a Text")
file.write_text contents encoding

Expand All @@ -130,7 +128,7 @@ write_text path contents (encoding=Encoding.utf_8) =

example_cwd = File.current_directory
current_directory : File
current_directory = File (here.get_cwd)
current_directory = here.get_cwd

## ALIAS Home Directory

Expand Down Expand Up @@ -204,10 +202,8 @@ type File
## PRIVATE

A type representing a file.

Arguments:
- prim_file: The internal representation of the file.
type File prim_file
@Builtin_Type
type File

## Creates a new output stream for this file and runs the specified action
on it.
Expand Down Expand Up @@ -235,6 +231,10 @@ type File
with_output_stream open_options action =
Resource.bracket (this.new_output_stream open_options) (_.close) action

output_stream options = @Builtin_Method "File.output_stream"

input_stream options = @Builtin_Method "File.input_stream"

## Creates a new input stream for this file and runs the specified action
on it.

Expand Down Expand Up @@ -377,20 +377,10 @@ type File

example_append = Examples.data_dir / "scratch_file"
/ : (Text | File) -> File
/ subpath = case subpath of
File prim -> File (this.prim_file.resolve prim)
_ -> File (this.prim_file.resolve subpath)
/ subpath = this.resolve subpath

## A text representation of this file.

> Example
Get a textual representation of a file.

import Standard.Examples

example_to_text = Examples.csv.to_text
to_text : Text
to_text = this.prim_file.to_text
resolve : (Text | File) -> File
resolve = @Builtin_Method "File.resolve"

## A File to JSON conversion.

Expand All @@ -412,7 +402,7 @@ type File

example_exists = Examples.csv.exists
exists : Boolean
exists = this.prim_file.exists
exists = @Builtin_Method "File.exists"

## Checks whether the file exists and is a directory.

Expand All @@ -423,7 +413,7 @@ type File

example_is_directory = Examples.csv.is_directory
is_directory : Boolean
is_directory = this.prim_file.isDirectory
is_directory = @Builtin_Method "File.is_directory"

## Creates the directory represented by this file if it did not exist.

Expand All @@ -437,7 +427,7 @@ type File
example_is_directory =
(Examples.data_dir / "my_directory") . create_directory
create_directory : Nothing
create_directory = this.prim_file.createDirectories
create_directory = @Builtin_Method "File.create_directory"

## Checks whether the file exists and is a regular file.

Expand All @@ -453,7 +443,7 @@ type File

example_is_regular_file = Examples.csv.is_regular_file
is_regular_file : Boolean
is_regular_file = this.prim_file.isRegularFile
is_regular_file = @Builtin_Method "File.is_regular_file"

## Resolves the parent filesystem node of this file.

Expand All @@ -464,7 +454,7 @@ type File

example_parent = Examples.csv.parent
parent : File
parent = File this.prim_file.getParent
parent = @Builtin_Method "File.parent"

## Returns the path of this file.

Expand All @@ -475,7 +465,7 @@ type File

example_path = Examples.csv.path
path : Text
path = this.prim_file.getPath
path = @Builtin_Method "File.path"

## Returns the name of this file.

Expand All @@ -486,7 +476,7 @@ type File

example_name = Examples.csv.name
name : Text
name = this.prim_file.getName
name = @Builtin_Method "File.name"

## Returns the extension of the file.

Expand Down Expand Up @@ -514,7 +504,7 @@ type File

example_absolute = Examples.csv.absolute
absolute : File
absolute = File this.prim_file.getAbsoluteFile
absolute = @Builtin_Method "File.absolute"

## Checks is this file's path is absolute.

Expand All @@ -525,7 +515,7 @@ type File

example_is_absolute = Examples.csv.is_absolute
is_absolute : Boolean
is_absolute = this.prim_file.isAbsolute
is_absolute = @Builtin_Method "File.is_absolute"

## Normalizes the filepath.

Expand All @@ -536,7 +526,7 @@ type File

example_normalize = Examples.csv.normalize
normalize : File
normalize = File this.prim_file.normalize
normalize = @Builtin_Method "File.normalize"

## Checks if this file has the same `path` as `that`.

Expand All @@ -547,7 +537,10 @@ type File

example_eq = Examples.csv == Examples.scratch_file
== : File -> Boolean
== that = this.prim_file.isEqual that.prim_file
== that = this.is_equal that

is_equal : File -> Boolean
is_equal that = @Builtin_Method "File.is_equal"

## Deletes the file.

Expand All @@ -565,7 +558,10 @@ type File
file.delete
delete : Nothing ! File_Error
delete =
here.handle_java_exceptions this this.prim_file.delete
here.handle_java_exceptions this this.delete_builtin

delete_builtin : Nothing
delete_builtin = @Builtin_Method "File.delete"

## Deletes the file if it exists on disk.

Expand Down Expand Up @@ -594,7 +590,7 @@ type File
new_input_stream : Vector.Vector -> Input_Stream ! File_Error
new_input_stream open_options =
opts = open_options . map (_.to_java) . to_array
stream = here.handle_java_exceptions this (this.prim_file.newInputStream opts)
stream = here.handle_java_exceptions this (this.input_stream opts)
resource = Managed_Resource.register stream here.close_stream
Input_Stream this resource

Expand All @@ -612,7 +608,7 @@ type File
new_output_stream open_options =
opts = open_options . map (_.to_java) . to_array
stream = here.handle_java_exceptions this <|
this.prim_file.newOutputStream opts
this.output_stream opts
resource = Managed_Resource.register stream here.close_stream
Output_Stream this resource

Expand Down Expand Up @@ -679,19 +675,24 @@ type File
fs = FileSystems.getDefault
matcher = fs.getPathMatcher "glob:"+name_filter
all_files.filter file->
pathStr = this.prim_file.relativize file.prim_file . getPath
pathStr = this.relativize file . path
matcher.matches (Path.of pathStr)
filtered

## UNSTABLE

Checks if `this` is a child path of `other`.
is_child_of other = this.prim_file.startsWith other.prim_file
is_child_of : File -> Boolean
is_child_of other = this.starts_with other

## UNSTABLE

Transforms `child` to a relative path with respect to `this`.
relativize child = File (this.prim_file.relativize child.prim_file)
relativize : File -> Boolean
relativize child = @Builtin_Method "File.relativize"

to_text : Text
to_text = this.absolute . path

## An output stream, allowing for interactive writing of contents into an
open file.
Expand Down Expand Up @@ -932,9 +933,11 @@ type File_Error
Utility function that lists immediate children of a directory.
list_immediate_children : File -> Vector.Vector File
list_immediate_children directory =
arr = directory.prim_file.list
Vector.new (Polyglot.get_array_size arr) ix->
File (arr.at ix)
arr = directory.list_immediate
Vector.Vector arr

list_immediate : File -> Array
list_immediate directory = @Builtin_Method "File.list_immediate"

## PRIVATE

Expand Down
4 changes: 2 additions & 2 deletions distribution/lib/Standard/Image/0.0.0-dev/src/Codecs.enso
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ polyglot java import org.enso.image.Codecs as Java_Codecs
read : (Text | File) -> (Read_Flag | Vector) -> Image ! File.Io_Error
read location flags=[] =
path = case location of
File.File _ -> location.path
File.File -> location.path
_ -> location
read_flags = case flags of
Vector.Vector _ ->
Expand Down Expand Up @@ -65,7 +65,7 @@ read location flags=[] =
Image.Image.write : (Text | File) -> (Write_Flag | Vector) -> Nothing ! File.Io_Error
Image.Image.write location flags=[] =
path = case location of
File.File _ -> location.path
File.File -> location.path
_ -> location
write_flags = case flags of
Vector.Vector _ -> flags
Expand Down
2 changes: 1 addition & 1 deletion distribution/lib/Standard/Table/0.0.0-dev/src/Io/Csv.enso
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ from_csv csv has_header=True prefix='C' =
Text ->
input_stream = ByteArrayInputStream.new csv.utf_8.to_array
Panic.catch Polyglot_Error (Table.Table (parser_inst.parse input_stream)) handle_error
File.File _ ->
File.File ->
Panic.catch Polyglot_Error handler=handle_error <|
csv.with_input_stream [File.Option.Read] stream->
stream.with_java_stream java_stream->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ File.read : (Text | File) -> File_Format -> Problem_Behavior -> Any ! File_Error
File.read path (format=File_Format.Auto) (on_problems=Report_Warning) =
file = case path of
Text -> (File.new path)
File.File _ -> path
File.File -> path
_ -> Error.throw (Illegal_Argument_Error "path should be either a File or a Text")
file.read format on_problems

Expand All @@ -40,4 +40,4 @@ File.read path (format=File_Format.Auto) (on_problems=Report_Warning) =
If set to `Ignore`, the operation proceeds without errors or warnings.
File.File.read : File_Format -> Problem_Behavior -> Any ! File_Error
File.File.read (format=File_Format.Auto) (on_problems=Report_Warning) =
format.read this on_problems
format.read this on_problems
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ file_uploading : (Base_File.File | Text) -> Base_File.File ! File_Being_Uploaded
file_uploading path =
err = File_Being_Uploaded <| case path of
Text -> path
Base_File.File _ -> path.path
Base_File.File -> path.path
_ -> ""
Error.throw err

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package org.enso.interpreter.node.controlflow.caseexpr;

import com.oracle.truffle.api.RootCallTarget;
import com.oracle.truffle.api.dsl.Fallback;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.interop.InteropLibrary;
import com.oracle.truffle.api.library.CachedLibrary;
import com.oracle.truffle.api.nodes.NodeInfo;
import com.oracle.truffle.api.profiles.ConditionProfile;
import org.enso.interpreter.runtime.callable.atom.Atom;
import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
import org.enso.interpreter.runtime.data.EnsoFile;

@NodeInfo(shortName = "FileMatch", description = "Allows matching on the File type.")
public abstract class FileBranchNode extends BranchNode {
private final AtomConstructor file;
private final ConditionProfile profile = ConditionProfile.createCountingProfile();

FileBranchNode(AtomConstructor file, RootCallTarget branch) {
super(branch);
this.file = file;
}

/**
* Create a new node to handle matching with the File constructor.
*
* @param file the constructor used for matching in this case
* @param branch the code to execute in this case
* @return a file branch node
*/
public static FileBranchNode build(AtomConstructor file, RootCallTarget branch) {
return FileBranchNodeGen.create(file, branch);
}

@Specialization
void doConstructor(VirtualFrame frame, Object state, Atom target) {
if (profile.profile(file == target.getConstructor())) {
accept(frame, state, target.getFields());
}
}

@Specialization
void doFile(VirtualFrame frame, Object state, EnsoFile target) {
accept(frame, state, new Object[0]);
}

@Fallback
void doFallback(VirtualFrame frame, Object state, Object target) {}
}
Loading

0 comments on commit aec60a5

Please sign in to comment.