https://github.com/trebor-huang/ice1000
🧊 A Elbereth Gilthoniel / silivren penna mÃriel! 🌟
https://github.com/trebor-huang/ice1000
programming-language
Last synced: 10 months ago
JSON representation
🧊 A Elbereth Gilthoniel / silivren penna mÃriel! 🌟
- Host: GitHub
- URL: https://github.com/trebor-huang/ice1000
- Owner: Trebor-Huang
- Created: 2022-04-15T11:57:24.000Z (about 4 years ago)
- Default Branch: main
- Last Pushed: 2022-06-25T02:14:03.000Z (almost 4 years ago)
- Last Synced: 2025-06-28T22:50:40.770Z (12 months ago)
- Topics: programming-language
- Language: Haskell
- Homepage:
- Size: 661 KB
- Stars: 19
- Watchers: 4
- Forks: 2
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# ice1000
> A Elbereth Gilthoniel
> silivren penna mÃriel!
A small programming language based on polarization.

# Techniques

(...)
# Sample Program

Pseudocode on what programs should look like.
```
-- Ordinary routines, Builtin functions
radius( a : Float , b : Float ) : Float
= sqrt( mulf(a,a) , mulf(b,b) )
-- No fancy infix but it's easy to add
-- Case
andb( a : Bool , b : Bool ) : Bool
= \case a, b { -- keywords are prefixed with a backslash
True() , True() => True()
-- Nullary constructors, to keep the parser simple
_ , _ => False()
}
-- Hindley Milnor Polymorphism
k( x : a , y : b ) : a = x
-- Case distinction with zero cases
falso( x : Void ) : a
= \case x {}
```
## Values and continuations
```
add_with_cont( x : Int , y : Int , c :~ Int ) : # -- Note the type!
= c # add(x , y) -- Combining a value with a continuation creates a #.
-- To create a continuation, do a pattern matching
example() :~ Int
= \continue {
1 => blabla -- Return a # here
2 => blabla
_ => blabla
}
```
## Effects
```
-- I/O
hw(cont :~ String) : #
= [] <- print("Your name, please: ")
; [name] <- input()
; [] <- print(concat("Hello, ", name))
; cont # name
-- So the syntax
-- [t1, t2, ...] <- effect(args) ; prog
-- carries out the effect, puts the result in the t's, and then carries out
-- prog of type #, where the variables t1, t2, ... can be used. The whole thing
-- again has type #. This operator is right associative, so you can chain.
-- Exiting is an effect.
exit() : #
= [v] <- abort() ; \case v {}
-- abort() returns a Void. During execution it directly exits the program.
-- This may seem slightly weird but it keeps the semantics uniform. Anyway you
-- can now use exit() directly to exit without doing this twist.
```
## Data structures
There is a slight subtlety in that we deliberately blur the difference of two
opposite things. So the explanation might get a little bit confusing.
Ordinary datatypes are straightforward:
```
-- A list of numbers (for simplicity, no polymorphism for now)
\data List { Nil() | Cons(head : Float, tail : List) }
-- You can still give names to these fields (Maybe I can automatically
-- generate projections? But I'm lazy), you can also choose to use
-- the _ wildcard.
append(a : List, b : List) : List
= \case a {
Nil() => b
Cons(x, xs) => Cons(x, append(xs, b))
}
```
The twist comes where you can also use the `:~` mechanism in datatypes:
```
\data Hole { Hole(_ :~ Float) }
```
(...)
We can have the eager/lazy distinction on data structures, but I'm too lazy.
Perhaps we have two keywords like `\eagerdata` and `\lazydata`, for which the
evaluation strategy will change accordingly. Currently I'm just going for all
call-by-need.
# Type theory

The type theory consists of judgements of the form
$$T_1, \dots, T_n; S_1, \dots, S_n \vdash J$$
where `J` is either `Program` or `By constructor T` or `By pattern S`.
A program (`#` in concrete syntax) is the result of combining a by-pattern term
with a by-constructor term. It can also be created by primitive effects. (...)
# Compiling
There are four stages:
- `ice1000` is the full language. After parsing, we translate away some small
syntactic sugars; do scope checking and remove all the module stuff.
- `ice100` is what's left. We then do type checking, and translate pattern matching
into case trees.
- `ice10` is what's left. This does not have type information now. And we proceed
to do more optimizations, and compile to bytecode or something
- `ice1` is the bytecode. Now we may run it in a VM or compile to binary.