Merge branch 'master' of https://github.com/dopefishh/cc1516
authorpimjager <pim@pimjager.nl>
Wed, 13 Apr 2016 19:50:25 +0000 (21:50 +0200)
committerpimjager <pim@pimjager.nl>
Wed, 13 Apr 2016 19:50:25 +0000 (21:50 +0200)
14 files changed:
examples/Markus/assignment_to_builtin.spl [new file with mode: 0644]
examples/Markus/higher_order_functions.spl [new file with mode: 0644]
examples/Markus/identity(2).spl [new file with mode: 0644]
examples/Markus/infinite_type_shouldfail.spl [new file with mode: 0644]
examples/Markus/multiple_recursion.spl [new file with mode: 0644]
examples/Markus/multiple_recursion_values.spl [new file with mode: 0644]
examples/Markus/overloading.spl [new file with mode: 0644]
examples/Markus/polymorphic_value_again_shouldfail.spl [new file with mode: 0644]
examples/Markus/polymorphic_value_shouldfail.spl [new file with mode: 0644]
examples/Markus/recursion.spl [new file with mode: 0644]
examples/Markus/self_application_shouldfail(1).spl [new file with mode: 0644]
examples/Markus/stress_test.spl [new file with mode: 0644]
ontwerpbesluiten.txt
sem.icl

diff --git a/examples/Markus/assignment_to_builtin.spl b/examples/Markus/assignment_to_builtin.spl
new file mode 100644 (file)
index 0000000..dc53a37
--- /dev/null
@@ -0,0 +1,13 @@
+// Do you allow this program?
+
+blaat(x) :: [a] -> Bool
+{
+  return True;
+}
+
+f()
+{
+  // This tries to assign to the built-in function isEmpty.
+  // Adapt this line if your isEmpty is called differently.
+  isEmpty = blaat;
+}
diff --git a/examples/Markus/higher_order_functions.spl b/examples/Markus/higher_order_functions.spl
new file mode 100644 (file)
index 0000000..717f881
--- /dev/null
@@ -0,0 +1,38 @@
+// Depending on your design decisions this might or might not compile.
+// In our course we don't require higher-order functions.
+// In fact, our grammar doesn't even allow function types in type signatures.
+// Anyway, this could be an idea for assignment 4.
+
+map(f, list)
+// This doesn't parse according to our grammar
+// :: (a -> b) [a] -> [b]
+{
+  if( isEmpty(list) )
+    return [];
+  else
+    return f(list.hd) : map(f, list.tl);
+}
+
+foldl(f, z, list)
+{
+  if( isEmpty(list) )
+    return z;
+  else
+    return foldl(f, f(z, list.hd), list.tl);
+}
+
+// Some operators wrapped in a function.
+plus(x, y) { return x + y; }
+and(b, c) { return b && c; }
+ge18(x) { return x >= 18; }
+
+// Sums all the elements of an Int list.
+sum(list) { return foldl(plus, 0, list); }
+
+// Checks whether all elements in a list of Booleans are True
+all(list) { return foldl(and, True, list); }
+
+// Checks whether in a list of numbers everybody is older than 18
+allOlderThan18(list) { return all(map(ge18, list)); }
+
+main() { return; }
diff --git a/examples/Markus/identity(2).spl b/examples/Markus/identity(2).spl
new file mode 100644 (file)
index 0000000..96232a2
--- /dev/null
@@ -0,0 +1,45 @@
+// Various versions of the identity function
+
+// Identity for integers
+// The type signature forces the function to have a more concrete type than it could have.
+id_int(x) :: Int -> Int
+{
+  return x;
+}
+
+
+// Polymorphic identity with type signature
+id_poly_with(x) :: a -> a
+{
+  return x;
+}
+
+
+// Polymorphic identity without type signature
+// Type checking should figure out the type forall a . a -> a
+id_poly_without(x)
+{
+  return x;
+}
+
+
+// Clumsy polymorphic identity
+// Type checking should give type forall a . a -> a
+id_poly_wtf(x)
+{
+  var a = x;
+  var b = a;
+  var c = b;
+  return c;
+}
+
+
+// Clumsy identity for integers
+// Type checking should give type Int -> Int
+id_int_wtf(x)
+{
+  var a = x;
+  Int b = a;
+  var c = b;
+  return c;
+}
diff --git a/examples/Markus/infinite_type_shouldfail.spl b/examples/Markus/infinite_type_shouldfail.spl
new file mode 100644 (file)
index 0000000..603cec0
--- /dev/null
@@ -0,0 +1,6 @@
+// An example from the slides. This should give a type error.
+
+f(x)
+{
+  return f( (x, x) );
+}
diff --git a/examples/Markus/multiple_recursion.spl b/examples/Markus/multiple_recursion.spl
new file mode 100644 (file)
index 0000000..8676358
--- /dev/null
@@ -0,0 +1,14 @@
+// Generates a list of zeros and ones
+
+flip(n, l)
+{
+  if( n <= 0 )
+    return l;
+  else
+    return flop(n-1, 0:l);
+}
+
+flop(n, l)
+{
+  return flip(n, 1:l);
+}
diff --git a/examples/Markus/multiple_recursion_values.spl b/examples/Markus/multiple_recursion_values.spl
new file mode 100644 (file)
index 0000000..171ee5a
--- /dev/null
@@ -0,0 +1,24 @@
+// Do you allow this?
+// Explain why or why not.
+
+var ones = 1:ones;
+
+var flip = 0:flop;
+var flop = 1:flip;
+
+// What about this?
+var flup = (flap.hd):flup;
+var flap = (flup.hd):flap;
+
+
+
+// For testing
+take(n, list)
+{
+  if( n <= 0 )
+    return [];
+  else
+    return list.hd : take(n-1, list.tl);
+}
+
+main() { print(take(10,flip)); }
diff --git a/examples/Markus/overloading.spl b/examples/Markus/overloading.spl
new file mode 100644 (file)
index 0000000..754da17
--- /dev/null
@@ -0,0 +1,7 @@
+// At this point you maybe don't see what the problem is.
+// Wait until you try to implement your code generator.
+
+equal(x, y)
+{
+  return x == y;
+}
diff --git a/examples/Markus/polymorphic_value_again_shouldfail.spl b/examples/Markus/polymorphic_value_again_shouldfail.spl
new file mode 100644 (file)
index 0000000..a9bda2e
--- /dev/null
@@ -0,0 +1,11 @@
+// Another variant of the polymorphic value problem.
+
+// This is perfectly fine
+var tuple1 = (1:[], True:[]);
+
+// This should fail.
+var l = [];
+var tuple2 = (1:l, True:l);
+
+
+main() { return; }
diff --git a/examples/Markus/polymorphic_value_shouldfail.spl b/examples/Markus/polymorphic_value_shouldfail.spl
new file mode 100644 (file)
index 0000000..0b868ee
--- /dev/null
@@ -0,0 +1,14 @@
+// This is an example why you need the value restriction.
+// This program should give a type error in some way.
+
+// The empty list [] usually has polymorphic type forall a.[a], but you
+// cannot give the variable l this type. See below what can go wrong.
+var l = [];
+
+f()
+{
+  // If l has polymorphic type forall a . [a], the next two lines are possible.
+  l = 1:l;
+  l = True:l;
+  return;
+}
diff --git a/examples/Markus/recursion.spl b/examples/Markus/recursion.spl
new file mode 100644 (file)
index 0000000..6dbd124
--- /dev/null
@@ -0,0 +1,14 @@
+// Greatest common divisor,
+// "The granddaddy of all algorithms, because it is the oldest nontrivial
+// algorithm that has survived to the present day." -- Don Knuth
+
+// This one only works for positive n, m
+gcd(m, n)
+{
+  if( n < m )
+    return gcd(n, m);
+  else if( n == m )
+    return n;
+  else // n > m
+    return gcd(m, n - m);
+}
diff --git a/examples/Markus/self_application_shouldfail(1).spl b/examples/Markus/self_application_shouldfail(1).spl
new file mode 100644 (file)
index 0000000..41397da
--- /dev/null
@@ -0,0 +1,6 @@
+// A classic from computer science.
+// The function \x.x x can not be typed in let-polymorphic type systems.
+f(x)
+{
+  return x(x);
+}
diff --git a/examples/Markus/stress_test.spl b/examples/Markus/stress_test.spl
new file mode 100644 (file)
index 0000000..11e52b2
--- /dev/null
@@ -0,0 +1,8 @@
+// Uncomment lines one by one. How far can you take your compiler?
+
+f0(x) { return (x, x); }
+f1(x) { return f0(f0(x)); }
+// f2(x) { return f1(f1(x)); }
+// f3(x) { return f2(f2(x)); }
+// f4(x) { return f3(f3(x)); }
+// f5(x) { return f4(f4(x)); }
index 8cbcf17..225ac74 100644 (file)
@@ -6,8 +6,13 @@ Staat mooie shizzle zoals in Haskell toe (f :: a -> a, g :: a -> a, f = g)
 Simpeler om te parsen
 Con: wellicht kut met code generatie, wie weet.
 
---
+---
 Functies en variabelen delen 1 namespace. 
 Dat is met het oog op hogere orde functies, dan kan een parameter voor een functie een andere 
 functie zijn, of een variabele en als die 2 aparte namespaces hebben is dat moeilijk onduidelijk / 
-praktisch onmogelijke met type inteference
\ No newline at end of file
+praktisch onmogelijke met type inteference
+
+
+---
+Functies kunnen voor correct typechecken alleen functies gebruiken die DAARNA 
+gedefinieerd zijn
\ No newline at end of file
diff --git a/sem.icl b/sem.icl
index a041cee..43df3a3 100644 (file)
--- a/sem.icl
+++ b/sem.icl
@@ -126,7 +126,6 @@ typeExpr (VarExpr p (VarDef ident fs)) = gets (\(st, r)->'Map'.get ident st)
     >>= \mt->case mt of
         Nothing = liftT $ Left $ UndeclaredVariableError p ident
         Just t = unify t fs
-
 typeOp2 :: Expr Expr Op2 [Type] Type -> Env Type
 typeOp2 e1 e2 op ts ret = typeExpr e1 >>= \t1-> typeExpr e2 >>= \t2->
     unify t1 t2 >>= \t3->if (isMember t3 ts) (pure ret)