Skip to content

Commit

Permalink
Merge pull request #37 from billhails/replace-typechecking
Browse files Browse the repository at this point in the history
Replace typechecking
  • Loading branch information
billhails authored Dec 31, 2023
2 parents 35b74c0 + d3b2a60 commit ed5765d
Show file tree
Hide file tree
Showing 54 changed files with 5,072 additions and 3,039 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ $(EXTRA_OBJ): obj/%.o: tmp/%.c | obj
$(LAXCC) -I src/ -I tmp/ -c $< -o $@

$(TEST_OBJ): obj/%.o: tests/src/%.c | obj
$(CC) -I src/ -I tmp/ -c $< -o $@
$(LAXCC) -I src/ -I tmp/ -c $< -o $@

$(MAIN_DEP) $(DEP): dep/%.d: src/%.c | dep
$(CC) -I tmp/ -I src/ -MM -MT $(patsubst dep/%,obj/%,$(patsubst %.d,%.o,$@)) -o $@ $<
Expand Down
5 changes: 5 additions & 0 deletions docs/LICENSES/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# LICENSES

This directory contains licenses for projects whose code I have used,
copied or made extensive reference to while working on CEKF.

7 changes: 6 additions & 1 deletion docs/LICENSE.bigint → docs/LICENSES/bigint.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
The following is the license that came with the bigint code I'm using.
It does *not* apply to the CEKF project as a whole.

Original project [983/bigint](https://github.com/983/bigint).

---

```
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
Expand All @@ -25,4 +30,4 @@ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org>

```
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
This is the license that comes with the re-entrant parser from
[gfrey](https://github.com/gfrey/reentrant_flex_bison_parser).
[gfrey/reentrant_flex_bison_parser](https://github.com/gfrey/reentrant_flex_bison_parser).

It does *not* apply to the whole of the CEKF project.

----

```
Copyright (c) 2015, Gereon Frey
All rights reserved.
Expand All @@ -30,3 +31,4 @@ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
```
31 changes: 31 additions & 0 deletions docs/LICENSES/type-inference.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
The following is the license that comes with the type-inference project
that I'm using as the basis for my type inference code. It does *not* apply
to the entire CEKF project.

Original source [k-mrm/type-inference](https://github.com/k-mrm/type-inference/tree/master).

---

```
MIT License
Copyright (c) 2019 mkei
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```
488 changes: 459 additions & 29 deletions docs/LambdaConversion.drawio

Large diffs are not rendered by default.

179 changes: 179 additions & 0 deletions fn/infer.fn
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
let
typedef typeExp {
varType(typeExp)
| operType(list(char), list(typeExp))
| nullType
}
typedef copyEnv {
cpEnv(typeExp, typeExp, copyEnv)
| nullCpEnv
}
typedef typeCheckEnv {
tcEnv(list(char), typeExp, typeCheckEnv)
| nullTcEnv
}
typedef ExpClass {
ideClass(list(char))
| condClass(ExpClass, ExpClass, ExpClass)
| lambClass(list(char), ExpClass)
| appClass(ExpClass, ExpClass)
| blockClass(DeclClass, ExpClass)
}
typedef DeclClass {
defClass(list(char), ExpClass)
| seqClass(DeclClass, DeclClass)
| recClass(Decl)
}
fn newTypeVar() { varType(nullType) }
fn prune {
(x = varType(nullType)) { x }
(varType(x)) { prune(x) }
(x) { x }
}
fn occursInType {
(var, type) {
switch(prune(type)) {
(x = varType(_)) { var == x }
(operType(_, args)) { occursInTypeList(var, args) }
}
}
}
fn occursInTypeList {
(_, []) { false }
(var, h @ t) { occursInType(var, h) or occursInTypeList(var, t) }
}
fn unifyType(exp1, exp2) {
switch (prune(exp1), prune(exp2)) {
(exp1=varType(_), exp2) {
if (occursInType(exp1, exp2)) {
exp1 == exp2
} else {
varType(exp2); // exp1.instance := exp2
true
}
}
(exp1, exp2=varType(_)) {
unifyType(exp2, exp1)
}
(operType(ide, args1), operType(ide, args2)) {
unifyArgs(args1, args2)
}
(_, _) {
false
}
}
}
fn unifyArgs {
([], []) { true }
(h1 @ t1, h2 @ t2) { unifyType(h1, h2) and unifyArgs(t1, t2) }
(_, _) { false }
}
fn isGeneric(var, ng) { not occursInTypeList(var, ng) }
fn freshVar {
(typeVar, nullCpEnv, envt) {
fn (fresh) {
#(fresh, copyEnv(fresh, typevar, envt))
} (newTypeVar())
}
(typeVar, cpEnv(old, new, parent), topEnv) {
if (typeVar == old) {
(new, topEnv)
} else {
freshVar(typeVar, parent, topEnv)
}
}
}
fn fresh(typeExp, ng, envt) {
switch(prune(typeExp)) {
(x = varType(_)) {
if (isGeneric(x, ng)) {
freshVar(x, envt, envt)
} else { x }
}
(operType(ide, args)) {
operType(ide, freshList(args, ng, envt))
}
}
}
fn freshList {
([], _, _) { [] }
(h @ t, ng, envt) {
fresh(h, ng, envt) @ freshList(t, ng, envt)
}
}
fn freshType(typeExp, ng) {
fresh(typeExp, ng, nullCpEnv)
}
fn retrieve {
(ide, tcEnv(ide, exp, _), ng) { freshType(exp, ng) }
(_, nullTcEnv, _) { error("unbound ide") }
(ide, tcEnv(_, _, tail), ng) { retrieve(ide, tail, ng) }
}
fn funType(dom, cod) { operType("->", [dom, cod]) }
fn analyzeExp {
(expClass(ide), envt, ng) { retrieve(ide, envt, ng) }
(condClass(test, cons, alt), envt, ng) {
unifyType(test, boolType) and
unifyType(analyzeExp(cons, envt, ng), analyzeExp(alt, envt, ng))
// return type of cons
}
(lambClass(binder, body), envt, ng) {
fn (typeOfBinder) {
funType(typeOfBinder,
analyzeExp(body, tcEnv(binder, typeOfBinder, envt),
typeOfBinder @ ng))
} (newTypeVar())
}
(appClass(fun, arg), envt, ng) {
fn (typeOfRes) {
unifyType(
analyzeExp(fun, envt, ng),
funType(analyzeExp(arg, envt, ng), typeOfRes));
typeOfRes
} (newTypeVar())
}
(blockClass(decl, scope), envt, ng) {
analyzeExp(scope, analyzeDecl(decl, envt, ng), ng)
}
}
fn analyzeDecl {
(defClass(binder, def), envt, ng) {
tcEnv(binder, analyzeExp(def, envt, ng), envt)
}
(seqClass(first, second), envt, ng) {
analyzeDecl(second, anayzeDecl(first, envt, ng), ng);
}
(recClass(rec), envt, ng) {
let
#(env2, ng2) = analyzeRecDeclBind(rec, envt, ng);
in
analyzeRecDecl(rec, env2, ng2);
env2
}
}
fn analyzeRecDeclBind {
(defClass(binder, _), envt, ng) {
fn (fresh) {
#(tcEnv(binder, fresh, envt), fresh @ ng)
} (newTypeVar())
}
(seqClass(first, second), envt, ng) {
let
#(env1, ng1) = analyzeRecDeclBind(first, envt, ng);
in
analyzeRecDeclBind(second, env1, ng1);
}
}
fn analyzeRecDecl {
(defClass(binder, def), envt, ng) {
unifyType(retrieve(binder, envt, ng),
analyzeExp(def, envt, ng))
}
(seqClass(first, second), envt, ng) {
analyzeRecDecl(first, envt, ng) and
analyzeRecDecl(second, envt, ng)
}
(recClass(rec), envt, ng) {
analyzeRec(rec, envt, ng)
}
}
1 change: 1 addition & 0 deletions fn/listOfInt.fn
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[1]
13 changes: 13 additions & 0 deletions fn/map3.fn
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
let
typedef colours { red | green | blue }
fn map {
(f, nil) { [] }
(f, h @ t) { f(h) @ map(f, t) }
}
fn toInt {
(red) { 0 }
(green) { 1 }
(blue) { 2 }
}
in
map(toInt, [red, green, blue])
Loading

0 comments on commit ed5765d

Please sign in to comment.