-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
23 changed files
with
302 additions
and
116 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/build |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
name = "TestProject" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import Spark/IO | ||
import Spark/List | ||
|
||
external "import { add } from './testproject_ffi.mjs';" | ||
external "let $id = 0;" | ||
|
||
def pub fresh_id = | ||
external "return $id++" | ||
|
||
const squares = List.map([1, 2, 3], \x -> x * x) | ||
|
||
def pub main = | ||
IO.println("Hello, world!") ; | ||
IO.println("Goodbye, now.") ; | ||
IO.println(squares) ; | ||
IO.println(@(fresh_id(), fresh_id(), fresh_id())) | ||
|
||
# Atoms don't need a name! Unnamed atoms are basically tuples. | ||
const me = @("Joe", 30) | ||
|
||
def pub first\@(a, _) = a | ||
def pub second\@(_, b) = b |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export function add(a, b) { | ||
return a + b; | ||
} |
Empty file.
Empty file.
Empty file.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,87 +1,46 @@ | ||
import filepath | ||
import gleam/io | ||
import gleam/result | ||
import spark/compile | ||
import spark/error | ||
import spark/lex | ||
import spark/parse | ||
import gleam/result.{try} | ||
import gleam/string | ||
import spark/file | ||
import spark/project | ||
import gleam_community/ansi | ||
|
||
pub fn main() { | ||
let source = | ||
" | ||
import Spark/IO | ||
external \"let $id = 0;\" | ||
def pub fresh_id = | ||
external \"return $id++\" | ||
def pub map\\over, fn = | ||
case over | ||
| [] as list = list | ||
| [x : xs] = fn(x) : map(xs, fn) | ||
const squares = map([1, 2, 3], \\x -> x * x) | ||
const foo = | ||
\\sum <- add_with_cb(5, 6) | ||
sum * (2 + 3 * external \"return 5\") | ||
const bar = | ||
[1, 2, 3] | ||
|> baz | ||
|> map(\\x -> x * x) | ||
def pub main = | ||
IO.println(\"Hello, world!\") ; | ||
\"Isn't this language nice?\" | ||
|> IO.println ; | ||
2 * 3 | ||
const dsf = | ||
case { x: 3, y: 5, z: 5 } | ||
| { x, y, z } = x + y + z | ||
| { x, y } = x + y | ||
let result = { | ||
use project <- try(project.from("TestProject", "examples/TestProject")) | ||
build(project) | ||
} | ||
|
||
def println\\text = | ||
@IO { | ||
perform: \\ -> external \" | ||
console.log(text); | ||
return $.nil; | ||
\" | ||
} | ||
case result { | ||
Ok(_) -> Nil | ||
Error(e) -> io.println_error(e) | ||
} | ||
} | ||
|
||
def then\\@IO { perform }, f = | ||
@IO { | ||
perform: \\ -> f(perform()).perform() | ||
} | ||
/// Build a project, with the stdlib and prelude included, to the /build directory. | ||
/// | ||
fn build(project: project.Project) -> Result(Nil, String) { | ||
let build_dir = filepath.join(project.dir, "build") | ||
|
||
def test = | ||
\\_ <- println(\"Hello!\") |> then | ||
println(\"Goodbye, now.\") | ||
report("Compiling", "Spark") | ||
use template <- try(project.from("Spark", "./templates")) | ||
use _ <- try(project.compile(template, to: build_dir)) | ||
|
||
# Atoms don't need a name! Unnamed atoms are basically tuples. | ||
const me = @(\"Joe\", 30) | ||
report("Compiling", project.name) | ||
use _ <- try(project.compile(project, to: build_dir)) | ||
|
||
def pub first\\@(a, _) = a | ||
def pub second\\@(_, b) = b | ||
" | ||
report("Creating", "index file") | ||
let path = filepath.join(project.dir, "build/index.mjs") | ||
let contents = "import { main } from './" <> project.name <> ".mjs';\nmain();" | ||
use _ <- try(file.write_all(path, contents)) | ||
|
||
let result = { | ||
use tokens <- result.try(lex.lex(source)) | ||
use ast <- result.try(parse.parse(tokens)) | ||
let compiled = compile.compile(ast) | ||
Ok(compiled) | ||
} | ||
report("Compiled", "successfully") | ||
report("Entry", path) | ||
Ok(Nil) | ||
} | ||
|
||
case result { | ||
Ok(js) -> { | ||
io.println(js) | ||
Nil | ||
} | ||
Error(e) -> | ||
error.to_string(e, source, "file.spark") | ||
|> io.println_error | ||
} | ||
fn report(status: String, message: String) { | ||
let padding = string.repeat(" ", 9 - string.length(status)) | ||
io.println(padding <> ansi.bold(ansi.blue(status)) <> " " <> message) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import filepath | ||
import gleam/result.{try} | ||
import gleam_community/ansi | ||
import simplifile | ||
|
||
/// Write a file, creating directories as needed. | ||
/// | ||
pub fn write_all(path: String, contents: String) -> Result(Nil, String) { | ||
let dir = filepath.directory_name(path) | ||
use _ <- try( | ||
simplifile.create_directory_all(dir) | ||
|> result.replace_error(file_error("create this directory", dir)), | ||
) | ||
simplifile.write(path, contents) | ||
|> result.replace_error(file_error("write to this file", path)) | ||
} | ||
|
||
/// Read a file. | ||
/// | ||
pub fn read(path: String) -> Result(String, String) { | ||
simplifile.read(path) | ||
|> result.replace_error(file_error("read this file", path)) | ||
} | ||
|
||
/// Copy a file at the first path to the second path. | ||
/// | ||
pub fn copy(from: String, to: String) -> Result(Nil, String) { | ||
simplifile.copy_file(from, to) | ||
|> result.replace_error(file_error("copy this file", from)) | ||
} | ||
|
||
/// List files in a directory. | ||
/// | ||
pub fn get_files(dir: String) -> Result(List(String), String) { | ||
simplifile.get_files(dir) | ||
|> result.replace_error(file_error("read this directory", dir)) | ||
} | ||
|
||
fn file_error(message, path) -> String { | ||
ansi.red("I was unable to " <> message <> ": ") <> path | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import filepath | ||
import gleam/list | ||
import gleam/string | ||
import spark/util | ||
|
||
// ---- TYPES ------------------------------------------------------------------ | ||
|
||
pub type Module { | ||
Module(segments: List(String), path: String) | ||
} | ||
|
||
// ---- CONSTRUCTOR ------------------------------------------------------------ | ||
|
||
pub fn from_path(path: String, inside_dir: String) -> Result(Module, Nil) { | ||
let stripped_path = | ||
path | ||
|> util.remove_prefix(inside_dir <> "/") | ||
|
||
let segments = filepath.split(stripped_path) | ||
|
||
case | ||
segments | ||
|> list.all(fn(segment) { | ||
util.capitalise(segment) == segment | ||
&& { | ||
filepath.extension(segment) == Ok("spark") | ||
|| filepath.strip_extension(segment) == segment | ||
} | ||
}) | ||
{ | ||
False -> Error(Nil) | ||
True -> | ||
segments | ||
|> list.map(filepath.strip_extension) | ||
|> Module(path) | ||
|> Ok | ||
} | ||
} | ||
|
||
// ---- FUNCTIONS -------------------------------------------------------------- | ||
|
||
/// Resolves an import from the given module to an import path, from the root of | ||
/// the project. | ||
/// | ||
pub fn resolve_import(module: Module, import_segments: List(String)) -> String { | ||
let prefix = case module.segments { | ||
[_] | [] -> "./" | ||
[_, ..rest] -> | ||
rest | ||
|> list.map(fn(_) { ".." }) | ||
|> string.join("/") | ||
<> "/" | ||
} | ||
|
||
prefix <> string.join(import_segments, with: "/") <> ".mjs" | ||
} |
Oops, something went wrong.