LILY (Lightweight Integrated List Syntax), is a Programming Language
This is the source code for LILY's compiler, implemented using OCaml.
Currently, the programming language implementation can be found in the src/
directory, and examples can be found in the test/
directory.
- Chimaobi Onwuka - ceo2134 - Language Guru
- Michaela Gary - mng2136 - Manager
- Ethan Thomas - emt2188 - System Architect
- Tani Omoyeni - tmo2121 - Tester
- Jianjie Sun - js6412 - Tester
- Indentation - Lily's parser uses indentation-style blocking (like Python) instead of bracket-style or C-style.
- Printing - The built in
print()
function can take an arbitrary number of primitive (Int
,Float
,Char
) arguments to print in Python-style. - List Printing - Calling
print(list)
on a single list will print the list nicely formatted. - Nested Functions - Lily allows for nested functions.
- Function Overloading - Lily allows for overloading functions.
- For loops and while loops - Lily supports
for
loops andwhile
loops in the style specified in the LRM. - For
in
loops - Lily supports iterating over a list in the stylefor element in list
. - Lists - Lily supports the declaration and referencing of
lists
in the style specified in the LRM. - Standard Functions -
stdlib.lily
containsprint
-ing functions,sum
,min
,max
, and more. - List Operations -
stdlib.lily
containsrange
,copy
,append
,remove
,reverse
,concatenate
, andpop
. - Sorting Functions -
stdlib.lily
containsmergesort
andselectionsort
functions, allowing the user to pick a preferred algorithm. - Search Functions -
stdlib.lily
containsbinarysearch
andsearch
(linear), allowing the user to pick the most efficient algorithm for their use case (sorted data vs. unsorted data). - "Pseudo-Randomness" -
stdlib.lily
contains a crude pseudorandom functionrandom(a, b)
. - Multi-List Functions -
stdlib.lily
containsshuffle(list1, list2)
andmerge(list1, list2)
. Users can also define their own multi-list functions.
-
scanner.mll
-
tokenize.ml
- This function acts as a middleman between the Scanner and the Parser to produceINDENT
,DEDENT
, andNEWLINE
tokens from detected indentation. -
parser.mly
-
ast.ml
test1
- tests parser and ast (everything above this) - to run test1
, run make test1
and follow the "How to run tests" instructions below.
-
presemant.ml
- Semantic checking pre-processing step. Allows conversion of singlestmts
into a list of multiplestmts
before being passed tosemant.ml
. Used to allow for functions that take generic lists as arguments. -
semant.ml
-
sast.ml
-
structs.ml
- Includes the definition of theFuncId
struct which is needed for theFuncMap
insemant.ml
, used for storing a map of functions (needed to allow for function overloading).
test2
- tests semantic checking (everything above this) - to run test2
, run make test2
and follow the "How to run tests" instructions below.
-
irgen.ml
-
stdlib.lily
- Standard library functions, written in LILY -
readers.ml
- Provides useful function definitions for reading from files and reading from stdin, needed to includestdlib.lily
functions in user programs.
lily.ml
- the compiler (tests everything) - to use, run make
and ./lily.native <filename.lily>
to compile files into llvm.
def grades_to_gpa_values(grades::char) -> float list:
let length: int = len(grades)
def grade_to_gpa_value(grade: char) -> float:
if (grade == 'A'):
return 4.0
if (grade == 'B'):
return 3.0
if (grade == 'C'):
return 2.0
if (grade == 'D'):
return 1.0
return 0.0
let gpas::float = []
for grade in grades:
let gpa: float = grade_to_gpa_value(grade)
gpas.append(gpa)
return gpas
let my_grades:: char = ['A', 'A', 'B', 'B', 'C', 'C', 'A', 'A', 'F']
my_grades.mergesort()
print(my_grades)
let my_gpas:: float = grades_to_gpa_values(my_grades)
print(my_gpas)
let gpa: float = sum(my_gpas) / flt(len(my_gpas))
print(gpa)
my_gpas.remove(0.0)
gpa = sum(my_gpas) / flt(len(my_gpas))
print(gpa)
The LILY compiler compiles. If you cannot get it to compile on your system, it is probably a PEBCAK
issue.
- OCaml - 5.1.1
- LLVM - 16.0.6
- opam package
llvm
- 16.0.6+nnp - opam package
dune
- 3.15.2
-
Install Ocaml, LLVM 16, and
opam
on your system (Process Varies). -
Create the
lily
environment switch with OCaml 5.1.1:
opam update
opam switch create lily 5.1.1
# For testing the original MicroC:
# opam switch create microc 4.14.2
# restart your shell
# and verify you're on switch lily:
# opam switch
- Install necessary packages:
opam install ocaml-lsp-server.1.17.0 odoc.2.4.2 ocamlformat.0.26.2 utop.2.14.0 dune.3.15.2 llvm.16.0.6+nnp
# For testing the original MicroC:
# opam install ocaml-lsp-server.1.17.0 odoc.2.4.2 ocamlformat.0.26.2 utop.2.14.0 dune.3.15.2 llvm.14.0.6
- Build the LILY compiler
# Enter the src/ code directory.
cd src/
make
This will produce a lily.native
file, the executable for your compiler. For standard library functions to work,
you must not move this executable file from the same directory as stdlib.lily
.
- Run the LILY compiler on a LILY script (such as the example above)
# This will produce LLVM IR code.
./lily.native ../text/oneslide.lily
# To actually run the script, pipe the LLVM IR code into lli
./lily.native ../text/oneslide.lily | lli
To automatically run all tests in the test/
folder, edit the LLI_COMMAND
field in run_tests.sh
to the lli
executable on your system, and run:
./run_tests.sh