-
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.
examples: Add examples I'm using to sketch out the grammar of the lan…
…guage
- Loading branch information
Showing
3 changed files
with
219 additions
and
0 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,91 @@ | ||
# This Source Form is subject to the terms of the AQUA Software License, | ||
# v. 1.0. Copyright (c) 2024 Aymeric Wibo | ||
|
||
## The install map maps file names to where they should be installed. | ||
## These destination paths are prefixed by the installation prefix, which can only be set by the user. | ||
## On most common Linux distributions, this would be '/usr' by default. | ||
## On FreeBSD, this is '/usr/local' by default. | ||
## | ||
## ```fl | ||
## install = { | ||
## "foo": "bin/foo", | ||
## "bar": "bin/bar", | ||
## } | ||
## ``` | ||
install: map<str, str> | ||
|
||
## Function to be called when the project is run. | ||
## The arguments passed to Bob are passed as a vector of strings to the `args` parameter. | ||
## The return value should be the exit code of the program (i.e. 0 on success and anything else on error). | ||
## | ||
## ```fl | ||
## fn run(args) { | ||
## return Sys.exec(cmd_path, args) | ||
## } | ||
## ``` | ||
## | ||
## In the above example, it is assumed that `cmd_path` is the path to an executable generated by the build step. | ||
fn run(args: vec<str>) -> int; | ||
|
||
## C compiler class. | ||
extern class CC { | ||
## Add a flag to the C compiler. | ||
## | ||
## ```fl | ||
## cc.add_opt("-std=c99") | ||
## ``` | ||
extern fn add_opt(self, option: str) -> void; | ||
|
||
## Compile a C source file. | ||
## Returns the path to the object file. | ||
## | ||
## ```fl | ||
## object_file_path = cc.compile("main.c") | ||
## ``` | ||
extern fn compile(self, src_path: str) -> str; | ||
} | ||
|
||
## Linker class. | ||
extern class Linker { | ||
## Create a static library ('.a') from a list of object files. | ||
## Returns the path to the static library. | ||
## | ||
## ```fl | ||
## lib_path = linker.static(["main.o", "foo.o", "bar.o"]) | ||
## ``` | ||
extern fn static(self, out_path: str) -> void; | ||
|
||
## Create a dynamic library (aka a shared object, '.so') from a list of object files. | ||
## The second argument is a list of other libraries to link against. | ||
## For example, if your library necessarily depends on 'libm', you would pass '["m"]' as the second argument. | ||
## Returns the path to the dynamic library. | ||
## | ||
## ```fl | ||
## lib_path = linker.dynamic(["main.o", "foo.o", "bar.o"]) | ||
## lib_path = linker.dynamic(["main.o", "foo.o", "bar.o"], ["m"]) | ||
## ``` | ||
extern fn dynamic(self, out_path: str, other_libs: vec<str> = []) -> void; | ||
|
||
## Create an executable from a list of object files. | ||
## The second argument is a list of other libraries to link against. | ||
## For example, if your library necessarily depends on 'libm', you would pass '["m"]' as the second argument. | ||
## Returns the path to the executable. | ||
## | ||
## ```fl | ||
## exe_path = linker.link(["main.o", "foo.o", "bar.o"]) | ||
## exe_path = linker.link(["main.o", "foo.o", "bar.o"], ["m"]) | ||
## ``` | ||
extern fn link(self, out_path: str, other_libs: vec<str> = []) -> void; | ||
} | ||
|
||
## Resource class. | ||
extern class Res { | ||
## Add a resource to the project. | ||
## This essentially copies your resource to the build directory untouched. | ||
## Returns the new path to the resource. | ||
## | ||
## ``` | ||
## res_path = res.add("header.h") | ||
## ``` | ||
extern pure fn add(path: str) -> str; | ||
} |
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,52 @@ | ||
# This Source Form is subject to the terms of the AQUA Software License, | ||
# v. 1.0. Copyright (c) 2024 Aymeric Wibo | ||
|
||
import std | ||
import bob | ||
|
||
# C compilation. | ||
|
||
cc = CC() | ||
|
||
cc.add_opt("-Isrc") | ||
cc.add_opt("-fPIC") | ||
cc.add_opt("-std=c99") | ||
cc.add_opt("-Wall") | ||
cc.add_opt("-Wextra") | ||
cc.add_opt("-Werror") | ||
|
||
lib_src = Fs.list("src/lib") | ||
.where(fn(path) path.ends_with(".c")) | ||
|
||
cmd_src = Fs.list("src/cmd") | ||
.where(fn(path) path.ends_with(".c")) | ||
|
||
src = lib_src ++ cmd_src | ||
src.map cc.compile | ||
|
||
# Create static & dynamic libraries and command-line frontend executable. | ||
|
||
linker = Linker() | ||
|
||
archive_path = linker.static(lib_src) | ||
dyn_lib_path = linker.dynamic(lib_src) | ||
cmd_path = linker.link(cmd_src, ["iar"]) | ||
|
||
# Add header as a resource. | ||
|
||
header_path = Res.add("src/iar.h") | ||
|
||
# How to run the command-line frontend? | ||
|
||
fn run(args) { | ||
return Sys.exec(cmd_path, args) | ||
} | ||
|
||
# Installation map. | ||
|
||
install = { | ||
cmd_path: "bin/iar", | ||
archive_path: "lib/libiar.a", | ||
dyn_lib_path: "lib/libiar.so", | ||
header_path: "include/iar.h", | ||
} |
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,76 @@ | ||
# This Source Form is subject to the terms of the AQUA Software License, | ||
# v. 1.0. Copyright (c) 2024 Aymeric Wibo | ||
|
||
## The `str` class provides methods on the builtin string type. | ||
extern class str { | ||
## *Check* if a string ends with the given suffix. | ||
|
||
## ```fl | ||
## s = "Hello world!" | ||
## assert s.ends_with("world!") == true | ||
## assert s.ends_with("world") == false | ||
## ``` | ||
extern pure fn ends_with(self, suffix: str) -> bool; | ||
} | ||
|
||
## The `vec` class provides methods on the builtin vector type. | ||
extern class vec { | ||
## Filter the elements of the vector based on a predicate. | ||
## For example, a list of numbers could be filtered to only include the even ones. | ||
## | ||
## ```fl | ||
## assert [1, 2, 3, 4, 5].where(fn(x) x % 2 == 0) === [2, 4] | ||
## ``` | ||
extern pure fn where(self, filter: fn(subject) -> bool) -> vec; | ||
|
||
## Apply a function to each element of the vector. | ||
## For example, a list of numbers could be squared. | ||
## | ||
## ```fl | ||
## assert [1, 2, 3, 4, 5].map(fn(x) x ** 2) === [1, 4, 9, 16, 25] | ||
## ``` | ||
extern pure fn map(self, action: fn(subject)) -> vec; | ||
|
||
## Concatenate two vectors. | ||
## | ||
## ```fl | ||
## assert [4, 2, 0] ++ [6, 9] === [4, 2, 0, 6, 9] | ||
## ``` | ||
extern pure fn ++(self, other: vec) -> vec; | ||
|
||
## Check if two vectors are equal. | ||
## | ||
## ```fl | ||
## assert ([4, 2, 0] === [4, 2, 0]) == true | ||
## assert ([4, 2, 0] === [4, 2, 1]) == false | ||
## ``` | ||
extern pure fn ===(self, other: vec) -> bool; | ||
} | ||
|
||
## The `Fs` class provides methods to interact with the filesystem. | ||
extern class Fs { | ||
## List the files in a directory. | ||
## If given a depth greater or equal to 0, it will list the files recursively up to the given depth. | ||
## A depth of -1 will list all files at an infinite depth. | ||
## The order of the entries is not guaranteed. | ||
## | ||
## ```fl | ||
## assert Fs.list(".") === [] # TODO | ||
## assert Fs.list(".", 0) === [] # TODO | ||
## assert Fs.list(".", 1) === [] # TODO | ||
## ``` | ||
extern pure fn list(path: str, depth: int = -1) -> vec<str>; | ||
} | ||
|
||
## The `Sys` class provides methods to interact with the system. | ||
extern class Sys { | ||
## Execute a command with arguments. | ||
## The command is executed in a new process. | ||
## The return value is the exit code of the command. | ||
## Capturing the standard output of the command is unsupported at the moment :( | ||
## | ||
## ```fl | ||
## assert Sys.exec("echo", ["Hello", "world!"]) == 0 | ||
## ``` | ||
extern pure fn exec(cmd: str, args: vec<str>) -> int; | ||
} |