diff --git a/pom.xml b/pom.xml
index b253672b2adb9e35e941ff2a509baf73b48a4020..e956045b26c53c9980bb8bba96fa9caa5d80f4cf 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
 
     <groupId>fr.insarennes.nperier</groupId>
     <artifactId>minichamo</artifactId>
-    <version>1.0-SNAPSHOT</version>
+    <version>0.7</version>
 
     <build>
         <plugins>
@@ -19,6 +19,20 @@
                 </configuration>
             </plugin>
 
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <version>3.2.2</version>
+                <configuration>
+                    <archive>
+                        <manifest>
+                            <addClasspath>true</addClasspath>
+                            <mainClass>fr.insarennes.nperier.minichamo.Main</mainClass>
+                        </manifest>
+                    </archive>
+                </configuration>
+            </plugin>
+
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-surefire-plugin</artifactId>
diff --git a/src/main/java/fr/insarennes/nperier/minichamo/language/definition/FunctionDef.java b/src/main/java/fr/insarennes/nperier/minichamo/language/definition/FunctionDef.java
index 6f4582cfab61a43ee7c8cc444220e0c6b27a4f7a..4b23ff28c005504fcb5754e58d0f7b98960cc4c0 100644
--- a/src/main/java/fr/insarennes/nperier/minichamo/language/definition/FunctionDef.java
+++ b/src/main/java/fr/insarennes/nperier/minichamo/language/definition/FunctionDef.java
@@ -1,6 +1,8 @@
 package fr.insarennes.nperier.minichamo.language.definition;
 
+import fr.insarennes.nperier.minichamo.language.Context;
 import fr.insarennes.nperier.minichamo.language.assignement.param.VarParam;
+import fr.insarennes.nperier.minichamo.language.expressions.Expression;
 import fr.insarennes.nperier.minichamo.language.typing.FunctionType;
 import fr.insarennes.nperier.minichamo.language.typing.GenericType;
 import fr.insarennes.nperier.minichamo.language.typing.Type;
@@ -10,6 +12,7 @@ import fr.insarennes.nperier.minichamo.utils.SymbolPosition;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 import java.util.stream.Collectors;
 
 public class FunctionDef extends VariableDef {
@@ -37,6 +40,24 @@ public class FunctionDef extends VariableDef {
         return this;
     }
 
+    @Override
+    public Type getType() {
+        List<Type> sp = new ArrayList<>();
+        for(VarParam p : params) {
+            sp.add(p.getType());
+        }
+        sp.add(expr.getType());
+        return new FunctionType(sp);
+    }
+
+    @Override
+    public void setExpression(final Expression e) {
+        expr = e;
+        Type effective = e.getType();
+        Map<String, Type> mapping = Type.unifyTwoMapping(returnType, effective);
+        replaceTypes(new ReplaceGenericsVisitor(mapping));
+    }
+
     public boolean isRecursive() {
         return recursive;
     }
@@ -49,6 +70,10 @@ public class FunctionDef extends VariableDef {
         return params;
     }
 
+    public VarParam getParam(int i) {
+        return params.get(i);
+    }
+
     public Type getReturnType() {
         return returnType;
     }
@@ -64,6 +89,7 @@ public class FunctionDef extends VariableDef {
         for(VarParam p : params) {
             sp.add(p.getType());
         }
+        sp.add(returnType);
         return new FunctionType(sp);
     }
 
@@ -80,6 +106,11 @@ public class FunctionDef extends VariableDef {
         return new FunctionDef(this);
     }
 
+    @Override
+    public VariableDef evalIfPossible(Context ctx) {
+        return this;
+    }
+
     @Override
     public boolean equals(Object o) {
         if(!(o instanceof FunctionDef)) {
diff --git a/src/main/java/fr/insarennes/nperier/minichamo/language/definition/ValueDef.java b/src/main/java/fr/insarennes/nperier/minichamo/language/definition/ValueDef.java
index 75499999acdc00b30fac7b0408bc99f1b6f180d0..f7827a85d37337f791cb72ace71a4dc0a79ad7b2 100644
--- a/src/main/java/fr/insarennes/nperier/minichamo/language/definition/ValueDef.java
+++ b/src/main/java/fr/insarennes/nperier/minichamo/language/definition/ValueDef.java
@@ -1,7 +1,8 @@
 package fr.insarennes.nperier.minichamo.language.definition;
 
+import fr.insarennes.nperier.minichamo.language.Context;
+import fr.insarennes.nperier.minichamo.language.expressions.Expression;
 import fr.insarennes.nperier.minichamo.language.typing.Type;
-import fr.insarennes.nperier.minichamo.language.typing.visitor.ReplaceGenericsVisitor;
 import fr.insarennes.nperier.minichamo.language.typing.visitor.TypeVisitor;
 import fr.insarennes.nperier.minichamo.utils.SymbolPosition;
 
@@ -14,11 +15,21 @@ public class ValueDef extends VariableDef {
         type = t;
     }
 
+    public ValueDef(String n, Expression e) {
+        super(n, null);
+        expr = e;
+    }
+
     public ValueDef(ValueDef vd) {
         super(vd);
         type = vd.type;
     }
 
+    @Override
+    public Type getType() {
+        return expr.getType();
+    }
+
     @Override
     protected Type getDeclaredType() {
         return type;
@@ -34,6 +45,12 @@ public class ValueDef extends VariableDef {
         return new ValueDef(this);
     }
 
+    @Override
+    public VariableDef evalIfPossible(Context ctx) {
+        setExpression(expr.evaluate(ctx));
+        return this;
+    }
+
     @Override
     protected void nameToDisplay(StringBuilder builder, String indent) {
         builder.append("let ").append(name).append(" : ").append(type);
diff --git a/src/main/java/fr/insarennes/nperier/minichamo/language/definition/VariableDef.java b/src/main/java/fr/insarennes/nperier/minichamo/language/definition/VariableDef.java
index 844e76f80795cb6682c42328c6c52e74a8098f85..2f24ca78a1c7de13c17d40560c997f030c57da7e 100644
--- a/src/main/java/fr/insarennes/nperier/minichamo/language/definition/VariableDef.java
+++ b/src/main/java/fr/insarennes/nperier/minichamo/language/definition/VariableDef.java
@@ -1,5 +1,6 @@
 package fr.insarennes.nperier.minichamo.language.definition;
 
+import fr.insarennes.nperier.minichamo.language.Context;
 import fr.insarennes.nperier.minichamo.language.expressions.Expression;
 import fr.insarennes.nperier.minichamo.language.typing.Type;
 import fr.insarennes.nperier.minichamo.language.typing.visitor.ReplaceGenericsVisitor;
@@ -13,7 +14,7 @@ import java.util.*;
 public abstract class VariableDef implements Displayable, Positioned {
 
     protected final String name;
-    private Expression expr;
+    protected Expression expr;
     private final List<NestedDefinition> nested;
     protected final SymbolPosition pos;
 
@@ -76,12 +77,16 @@ public abstract class VariableDef implements Displayable, Positioned {
         getExpression().replaceTypes(visitor);
     }
 
+    abstract public Type getType();
+
     abstract public void completeDeclaredType(TypeVisitor<Type> visitor);
 
     abstract protected void nameToDisplay(StringBuilder builder, String indent);
 
     abstract public VariableDef duplicate();
 
+    abstract public VariableDef evalIfPossible(Context ctx);
+
     abstract protected Type getDeclaredType();
 
     @Override
diff --git a/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/ConditionExpression.java b/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/ConditionExpression.java
index 79b450da91c4c0c8fb7bec351488f927c22588f4..df935d4bb4db5908fab67d95c208acae996ce8e4 100644
--- a/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/ConditionExpression.java
+++ b/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/ConditionExpression.java
@@ -68,6 +68,11 @@ public class ConditionExpression extends Expression {
         return condition.isComplex() || yes.isComplex() || no.isComplex();
     }
 
+    @Override
+    public boolean isSeveralWords() {
+        return true;
+    }
+
     @Override
     public void toDisplay(StringBuilder builder, String indent) {
         if(isComplex()) {
diff --git a/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/ConstructorExpression.java b/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/ConstructorExpression.java
new file mode 100644
index 0000000000000000000000000000000000000000..5edd5d5d3f6849903a25a7bbca908209a8082c18
--- /dev/null
+++ b/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/ConstructorExpression.java
@@ -0,0 +1,5 @@
+package fr.insarennes.nperier.minichamo.language.expressions;
+
+public class ConstructorExpression {
+
+}
diff --git a/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/Expression.java b/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/Expression.java
index 1cfc48391a57b306124e0a2818ef0306ca9d10a7..905420efe478ac7ef99ff705d72e4d728b642107 100644
--- a/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/Expression.java
+++ b/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/Expression.java
@@ -21,6 +21,8 @@ public abstract class Expression implements Displayable {
 
     public abstract boolean isComplex();
 
+    public abstract boolean isSeveralWords();
+
     public Expression duplicate() {
         return acceptVisitor(new DuplicateExpressionVisitor());
     }
diff --git a/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/FunctionCallExpression.java b/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/FunctionCallExpression.java
new file mode 100644
index 0000000000000000000000000000000000000000..3ec071216e9c31cd0a69694b4a3e50dd35df6263
--- /dev/null
+++ b/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/FunctionCallExpression.java
@@ -0,0 +1,88 @@
+package fr.insarennes.nperier.minichamo.language.expressions;
+
+import fr.insarennes.nperier.minichamo.language.Context;
+import fr.insarennes.nperier.minichamo.language.definition.FunctionDef;
+import fr.insarennes.nperier.minichamo.language.definition.ValueDef;
+import fr.insarennes.nperier.minichamo.language.expressions.visitor.ExpressionArgVisitor;
+import fr.insarennes.nperier.minichamo.language.expressions.visitor.ExpressionVisitor;
+import fr.insarennes.nperier.minichamo.language.typing.FunctionType;
+import fr.insarennes.nperier.minichamo.language.typing.Type;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class FunctionCallExpression extends Expression {
+
+    private final FunctionDef fun;
+    private final List<Expression> args;
+
+    public FunctionCallExpression(final FunctionDef f, final List<Expression> el) {
+        fun = f;
+        args = new ArrayList<>(el);
+        // TODO unification
+    }
+
+    public FunctionDef getFunction() {
+        return fun;
+    }
+
+    public List<Expression> getArgs() {
+        return args;
+    }
+
+    @Override
+    public Expression evaluate(Context ctx) {
+        Context ctx1 = ctx.duplicate();
+        for(int i = 0; i < fun.getNbParams(); i++) {
+            Expression val = args.get(i).evaluate(ctx);
+            String n = fun.getParam(i).getVar();
+            ctx1.addVariable(new ValueDef(n, val));
+        }
+        return fun.getExpression().evaluate(ctx1);
+    }
+
+    @Override
+    public Type getType() {
+        List<Type> sp = new ArrayList<>();
+        for(Expression arg : args) {
+            sp.add(arg.getType());
+        }
+        sp.add(fun.getReturnType());
+        return new FunctionType(sp);
+    }
+
+    @Override
+    public <T> T acceptVisitor(ExpressionVisitor<T> visitor) {
+        return null;
+    }
+
+    @Override
+    public <V, T> T acceptVisitor(ExpressionArgVisitor<V, T> visitor, V arg) {
+        return null;
+    }
+
+    @Override
+    public boolean isComplex() {
+        return args.stream().anyMatch(Expression::isComplex);
+    }
+
+    @Override
+    public boolean isSeveralWords() {
+        return true;
+    }
+
+    @Override
+    public void toDisplay(StringBuilder builder, String indent) {
+        builder.append(fun.getName());
+        for(Expression e : args) {
+            builder.append(" ");
+            if(e.isSeveralWords()) {
+                builder.append("(");
+                e.toDisplay(builder, indent);
+                builder.append(")");
+            } else {
+                e.toDisplay(builder, indent);
+            }
+        }
+    }
+}
diff --git a/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/MatchExpression.java b/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/MatchExpression.java
new file mode 100644
index 0000000000000000000000000000000000000000..1fbe68f6dbddd31d81250f9ef39544f125f44203
--- /dev/null
+++ b/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/MatchExpression.java
@@ -0,0 +1,4 @@
+package fr.insarennes.nperier.minichamo.language.expressions;
+
+public class MatchExpression {
+}
diff --git a/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/NameExpression.java b/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/NameExpression.java
index 8d692738862a2892168ce27949eccbff12bec7fd..be9c76fe2d4ce72c5da4f0e53aad831ee2d1d68c 100644
--- a/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/NameExpression.java
+++ b/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/NameExpression.java
@@ -72,6 +72,11 @@ public class NameExpression extends Expression {
         return false;
     }
 
+    @Override
+    public boolean isSeveralWords() {
+        return false;
+    }
+
     @Override
     public void toDisplay(StringBuilder builder, String indent) {
         builder.append(name);
diff --git a/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/NupleExpression.java b/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/NupleExpression.java
index 687d83f869acb361baf1420f827ef3016e413223..62743ff0d8de07c11e247b3bf8111a1ea2e716e8 100644
--- a/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/NupleExpression.java
+++ b/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/NupleExpression.java
@@ -35,12 +35,12 @@ public class NupleExpression extends Expression {
 
     @Override
     public <T> T acceptVisitor(ExpressionVisitor<T> visitor) {
-        return null;
+        return visitor.visitNuple(this);
     }
 
     @Override
     public <V, T> T acceptVisitor(ExpressionArgVisitor<V, T> visitor, V arg) {
-        return null;
+        return visitor.visitNuple(this, arg);
     }
 
     @Override
@@ -48,25 +48,27 @@ public class NupleExpression extends Expression {
         return streamElements().anyMatch(Expression::isComplex);
     }
 
+    @Override
+    public boolean isSeveralWords() {
+        return true;
+    }
+
     @Override
     public void toDisplay(StringBuilder builder, String indent) {
         if(isComplex()) {
             String indent1 = indent + "\t";
-            builder.append("(\n").append(indent1);
+            builder.append("\n").append(indent1);
             elts.get(0).toDisplay(builder, indent1);
             for(int i = 1; i < elts.size(); i++) {
                 builder.append(",\n").append(indent1);
                 elts.get(i).toDisplay(builder, indent1);
-            }
-            builder.append("\n").append(indent).append(")");
+            };
         } else {
-            builder.append("(");
             elts.get(0).toDisplay(builder, indent);
             for(int i = 1; i < elts.size(); i++) {
                 builder.append(", ");
                 elts.get(i).toDisplay(builder, indent);
             }
-            builder.append(")");
         }
     }
 }
diff --git a/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/PartialFunctionCallExpression.java b/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/PartialFunctionCallExpression.java
new file mode 100644
index 0000000000000000000000000000000000000000..3d966269482f024a4de8185061c3c935a2831595
--- /dev/null
+++ b/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/PartialFunctionCallExpression.java
@@ -0,0 +1,4 @@
+package fr.insarennes.nperier.minichamo.language.expressions;
+
+public class PartialFunctionCallExpression {
+}
diff --git a/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/VarExpression.java b/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/VarExpression.java
index e33dbb3144431366a21c8d2f96d95add8a01549a..4b2091dfbe38c03f68fd2c35b182a844726a2024 100644
--- a/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/VarExpression.java
+++ b/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/VarExpression.java
@@ -28,7 +28,7 @@ public class VarExpression extends Expression {
 
     @Override
     public Type getType() {
-        return vard.getExpression().getType();
+        return vard.getType();
     }
 
     @Override
@@ -55,6 +55,11 @@ public class VarExpression extends Expression {
         return false;
     }
 
+    @Override
+    public boolean isSeveralWords() {
+        return false;
+    }
+
     @Override
     public void toDisplay(StringBuilder builder, String indent) {
         builder.append(vard.getName());
diff --git a/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/base/BaseExpression.java b/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/base/BaseExpression.java
index 51ea64f898257d1cdfa690e34de7e8daba485d54..67267ff38ddaaed2f8f007bca71e2f93872f668f 100644
--- a/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/base/BaseExpression.java
+++ b/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/base/BaseExpression.java
@@ -27,6 +27,11 @@ public abstract class BaseExpression extends Expression {
         return false;
     }
 
+    @Override
+    public boolean isSeveralWords() {
+        return false;
+    }
+
     @Override
     public void toDisplay(StringBuilder builder, String indent) {
         builder.append(toString());
diff --git a/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/visitor/DuplicateExpressionVisitor.java b/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/visitor/DuplicateExpressionVisitor.java
index 6e059629638b3a01acce5c89f66ec02aa845b5b5..a118e2dd741ac1011a5576c3993ba9760ec58555 100644
--- a/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/visitor/DuplicateExpressionVisitor.java
+++ b/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/visitor/DuplicateExpressionVisitor.java
@@ -1,5 +1,6 @@
 package fr.insarennes.nperier.minichamo.language.expressions.visitor;
 
+import fr.insarennes.nperier.minichamo.language.definition.FunctionDef;
 import fr.insarennes.nperier.minichamo.language.expressions.*;
 import fr.insarennes.nperier.minichamo.language.expressions.base.BaseExpression;
 
@@ -35,4 +36,12 @@ public class DuplicateExpressionVisitor extends SimpleExpressionVisitor<Expressi
     public Expression visitNuple(NupleExpression e) {
         return new NupleExpression(e.streamElements().map(elt -> elt.acceptVisitor(this)).collect(Collectors.toList()));
     }
+
+    @Override
+    public Expression visitFunction(FunctionCallExpression e) {
+        return new FunctionCallExpression(
+                (FunctionDef) e.getFunction().duplicate(),
+                e.getArgs().stream().map(arg -> arg.acceptVisitor(this)).collect(Collectors.toList())
+        );
+    }
 }
diff --git a/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/visitor/ExpressionArgVisitor.java b/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/visitor/ExpressionArgVisitor.java
index c883681ca17dd7181749558e7907feedd41b4382..54ecdf6569307c09c58e59b4b80fedd268fab21f 100644
--- a/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/visitor/ExpressionArgVisitor.java
+++ b/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/visitor/ExpressionArgVisitor.java
@@ -1,9 +1,6 @@
 package fr.insarennes.nperier.minichamo.language.expressions.visitor;
 
-import fr.insarennes.nperier.minichamo.language.expressions.ConditionExpression;
-import fr.insarennes.nperier.minichamo.language.expressions.NameExpression;
-import fr.insarennes.nperier.minichamo.language.expressions.NupleExpression;
-import fr.insarennes.nperier.minichamo.language.expressions.VarExpression;
+import fr.insarennes.nperier.minichamo.language.expressions.*;
 import fr.insarennes.nperier.minichamo.language.expressions.base.*;
 
 public interface ExpressionArgVisitor<V,T> {
@@ -28,4 +25,6 @@ public interface ExpressionArgVisitor<V,T> {
 
     T visitNuple(NupleExpression e, V arg);
 
+    T visitFunction(FunctionCallExpression e, V arg);
+
 }
diff --git a/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/visitor/ExpressionVisitor.java b/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/visitor/ExpressionVisitor.java
index aa11146e8c34187c6a512ef037830c215e9de818..9b1695a0bfd4d09080bdea9a40476de1cfa48b8a 100644
--- a/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/visitor/ExpressionVisitor.java
+++ b/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/visitor/ExpressionVisitor.java
@@ -1,9 +1,6 @@
 package fr.insarennes.nperier.minichamo.language.expressions.visitor;
 
-import fr.insarennes.nperier.minichamo.language.expressions.ConditionExpression;
-import fr.insarennes.nperier.minichamo.language.expressions.NameExpression;
-import fr.insarennes.nperier.minichamo.language.expressions.NupleExpression;
-import fr.insarennes.nperier.minichamo.language.expressions.VarExpression;
+import fr.insarennes.nperier.minichamo.language.expressions.*;
 import fr.insarennes.nperier.minichamo.language.expressions.base.*;
 
 public interface ExpressionVisitor<T> {
@@ -28,4 +25,6 @@ public interface ExpressionVisitor<T> {
 
     T visitNuple(NupleExpression e);
 
+    T visitFunction(FunctionCallExpression e);
+
 }
diff --git a/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/visitor/GetNamesVisitor.java b/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/visitor/GetNamesVisitor.java
index 14bfb1f2d2203805e494033dddf184ad3ce9b9da..6b2da8eb587c1e3360efa27902a93f64ce005c57 100644
--- a/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/visitor/GetNamesVisitor.java
+++ b/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/visitor/GetNamesVisitor.java
@@ -1,13 +1,12 @@
 package fr.insarennes.nperier.minichamo.language.expressions.visitor;
 
-import fr.insarennes.nperier.minichamo.language.expressions.ConditionExpression;
-import fr.insarennes.nperier.minichamo.language.expressions.NameExpression;
-import fr.insarennes.nperier.minichamo.language.expressions.NupleExpression;
-import fr.insarennes.nperier.minichamo.language.expressions.VarExpression;
+import fr.insarennes.nperier.minichamo.language.assignement.param.VarParam;
+import fr.insarennes.nperier.minichamo.language.expressions.*;
 import fr.insarennes.nperier.minichamo.language.expressions.base.BaseExpression;
 
 import java.util.HashSet;
 import java.util.Set;
+import java.util.stream.Collectors;
 
 public class GetNamesVisitor extends SimpleExpressionVisitor<Set<String>> {
 
@@ -42,4 +41,12 @@ public class GetNamesVisitor extends SimpleExpressionVisitor<Set<String>> {
         return res;
     }
 
+    @Override
+    public Set<String> visitFunction(FunctionCallExpression e) {
+        final Set<String> res = new HashSet<>();
+        for(Expression arg : e.getArgs()) {
+            res.addAll(arg.acceptVisitor(this));
+        }
+        return res;
+    }
 }
diff --git a/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/visitor/TypeReplacementVisitor.java b/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/visitor/TypeReplacementVisitor.java
index b0e1b686ca9fbcbddbbb7d752aa348ccdeb1358b..55c274632f9c41482323c92cf903a4fb5cf5969f 100644
--- a/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/visitor/TypeReplacementVisitor.java
+++ b/src/main/java/fr/insarennes/nperier/minichamo/language/expressions/visitor/TypeReplacementVisitor.java
@@ -1,9 +1,6 @@
 package fr.insarennes.nperier.minichamo.language.expressions.visitor;
 
-import fr.insarennes.nperier.minichamo.language.expressions.ConditionExpression;
-import fr.insarennes.nperier.minichamo.language.expressions.NameExpression;
-import fr.insarennes.nperier.minichamo.language.expressions.NupleExpression;
-import fr.insarennes.nperier.minichamo.language.expressions.VarExpression;
+import fr.insarennes.nperier.minichamo.language.expressions.*;
 import fr.insarennes.nperier.minichamo.language.expressions.base.BaseExpression;
 import fr.insarennes.nperier.minichamo.language.typing.Type;
 import fr.insarennes.nperier.minichamo.language.typing.visitor.ReplaceGenericsVisitor;
@@ -53,4 +50,11 @@ public class TypeReplacementVisitor extends SimpleExpressionVisitor<Void> {
         e.streamElements().forEach(elt -> elt.acceptVisitor(this));
         return null;
     }
+
+    @Override
+    public Void visitFunction(FunctionCallExpression e) {
+        e.getArgs().forEach(arg -> arg.acceptVisitor(this));
+        e.getFunction().replaceTypes(visitor);
+        return null;
+    }
 }
diff --git a/src/main/java/fr/insarennes/nperier/minichamo/language/typing/AliasType.java b/src/main/java/fr/insarennes/nperier/minichamo/language/typing/AliasType.java
index e80e7a32000ea8e2c4f95a29d5e4541b52d8f677..b30a804a148977e2cca459f2d07645c944585292 100644
--- a/src/main/java/fr/insarennes/nperier/minichamo/language/typing/AliasType.java
+++ b/src/main/java/fr/insarennes/nperier/minichamo/language/typing/AliasType.java
@@ -29,7 +29,7 @@ public class AliasType extends Type {
     }
 
     @Override
-    public Type specify(Type[] sp) { // TODO propagate
+    public Type specify(Type[] sp) {
         int arity = getArity();
         if(sp.length != arity) {
             throw new ParsingException("Alias type " + getName() + " has an arity of " + arity + " but got " + sp.length + " types");
diff --git a/src/main/java/fr/insarennes/nperier/minichamo/language/typing/SumType.java b/src/main/java/fr/insarennes/nperier/minichamo/language/typing/SumType.java
index aa927a99686ae552098ac2c5ddb8d08ef6a773ac..798c08e823937a2e58a5e0ec80bc08201a7d9758 100644
--- a/src/main/java/fr/insarennes/nperier/minichamo/language/typing/SumType.java
+++ b/src/main/java/fr/insarennes/nperier/minichamo/language/typing/SumType.java
@@ -144,13 +144,6 @@ public class SumType extends Type {
     public boolean equals(Object o) {
         if(super.equals(o)) {
             SumType t = (SumType) o;
-
-            for(int i = 0; i < lconstructors.size(); i++) {
-                if(! getConstructor(i).equals(t.getConstructor(i))) {
-                    System.out.println(getConstructor(i));
-                    System.out.println(t.getConstructor(i));
-                }
-            }
             return getConstructors().equals(t.getConstructors());
         }
         return false;
diff --git a/src/main/java/fr/insarennes/nperier/minichamo/parsing/AssignementParser.java b/src/main/java/fr/insarennes/nperier/minichamo/parsing/AssignementParser.java
index 2cad1bb61878e51edcaedb828b1bff4d69d2bd9c..0845227f0481fd4a70d094d612cf4b0b748b66c3 100644
--- a/src/main/java/fr/insarennes/nperier/minichamo/parsing/AssignementParser.java
+++ b/src/main/java/fr/insarennes/nperier/minichamo/parsing/AssignementParser.java
@@ -5,7 +5,6 @@ import fr.insarennes.nperier.minichamo.language.Context;
 import fr.insarennes.nperier.minichamo.language.assignement.param.VarParam;
 import fr.insarennes.nperier.minichamo.language.definition.FunctionDef;
 import fr.insarennes.nperier.minichamo.language.definition.TypeDef;
-import fr.insarennes.nperier.minichamo.language.definition.ValueDef;
 import fr.insarennes.nperier.minichamo.language.definition.VariableDef;
 import fr.insarennes.nperier.minichamo.language.expressions.Expression;
 import fr.insarennes.nperier.minichamo.lexing.tokens.TokenType;
@@ -17,7 +16,9 @@ import java.util.stream.Collectors;
 public class AssignementParser {
 
     public static VariableDef parse(final TokenPeekIterator it, final Context context) {
-        return parse(it, context, true);
+        VariableDef res = parse(it, context, true);
+        context.addVariable(res);
+        return res;
     }
 
     protected static VariableDef parse(final TokenPeekIterator it, final Context context, boolean check) {
diff --git a/src/main/java/fr/insarennes/nperier/minichamo/parsing/ExpressionParser.java b/src/main/java/fr/insarennes/nperier/minichamo/parsing/ExpressionParser.java
index bed4540a048d33ca538fa87404dd28e1746a776f..b14e9c9bb6054cfbb111d2b1c652c66c9d8ae494 100644
--- a/src/main/java/fr/insarennes/nperier/minichamo/parsing/ExpressionParser.java
+++ b/src/main/java/fr/insarennes/nperier/minichamo/parsing/ExpressionParser.java
@@ -52,16 +52,20 @@ public class ExpressionParser {
         return new ConditionExpression(cond, e1, e2);
     }
 
+    // public static Expression parseNameThenMaybeFunction(TokenPeekIterator it, Context ctx, Counter cpt) {
+    //     TODO
+    // }
+
     public static Optional<Expression> parseSimple(TokenPeekIterator it, Context ctx, Counter cpt) {
         if(it.peekIs(TokenType.NAME)) {
             return Optional.of(parseName(it, ctx, cpt));
         }
-        if(it.peekIs(TokenType.CONSTRUCT_NAME)) {
-            // TODO
-        }
-        if(it.junkIf(TokenType.LBRACKET)) {
-            // TODO
-        }
+        // if(it.peekIs(TokenType.CONSTRUCT_NAME)) {
+        //     TODO
+        // }
+        // if(it.junkIf(TokenType.LBRACKET)) {
+        //     TODO
+        // }
         if(it.junkIf(TokenType.LPAREN)) {
             return Optional.of(parseInParen(it, ctx));
         }
diff --git a/src/main/java/fr/insarennes/nperier/minichamo/parsing/Parser.java b/src/main/java/fr/insarennes/nperier/minichamo/parsing/Parser.java
index e4f902cdaade63d6587106940720a958f9a8ba82..c5e2812f720bee702acbcb38e8bdba0094aaff56 100644
--- a/src/main/java/fr/insarennes/nperier/minichamo/parsing/Parser.java
+++ b/src/main/java/fr/insarennes/nperier/minichamo/parsing/Parser.java
@@ -1,7 +1,11 @@
 package fr.insarennes.nperier.minichamo.parsing;
 
+import fr.insarennes.nperier.minichamo.errors.ParsingException;
 import fr.insarennes.nperier.minichamo.language.Context;
+import fr.insarennes.nperier.minichamo.language.definition.FunctionDef;
 import fr.insarennes.nperier.minichamo.language.definition.TypeDef;
+import fr.insarennes.nperier.minichamo.language.definition.VariableDef;
+import fr.insarennes.nperier.minichamo.language.typing.Type;
 import fr.insarennes.nperier.minichamo.lexing.Lexer;
 import fr.insarennes.nperier.minichamo.lexing.tokens.TokenType;
 import fr.insarennes.nperier.minichamo.utils.TokenPeekIterator;
@@ -17,14 +21,32 @@ public class Parser {
     public void parse(Lexer lexer) {
         TokenPeekIterator it = new TokenPeekIterator(lexer);
         while(it.hasNext()) {
-            if(it.next().getType() == TokenType.TYPEDEF) {
+            if(it.junkIf(TokenType.TYPEDEF)) {
                 TypeDef td = TypedefParser.parse(it, ctx);
                 if(it.peek().getType() == TokenType.TERMINATION) {
                     it.junk();
                 }
-                System.out.println(td);
+                td.display();
+            } else if(it.junkIf(TokenType.LET)) {
+                VariableDef vd = AssignementParser.parse(it, ctx);
+                if(it.peek().getType() == TokenType.TERMINATION) {
+                    it.junk();
+                }
+                vd.display();
+                String name = vd.getName();
+                if(name.startsWith("_")) {
+                    name = "-";
+                }
+                Type type = vd.getType();
+                if(vd instanceof FunctionDef) {
+                    System.out.println(name + " : " + type + " = <fun>");
+                } else if(!"()".equals(name)) {
+                    System.out.println(name + " : " + type + " = " + vd.getExpression().evaluate(ctx));
+                }
+            } else {
+                throw new ParsingException("Expected type declaration or variable assignment, got " + it.peek(), it);
             }
-            //System.out.println(TypeParser.parse(it, ctx));
+            System.out.println("");
         }
     }
 
diff --git a/src/main/java/fr/insarennes/nperier/minichamo/parsing/TypedefParser.java b/src/main/java/fr/insarennes/nperier/minichamo/parsing/TypedefParser.java
index a1bca33f90aee66226c30b71fda655d797e83938..74d711eafe3fcdd8c43f0c63198a7a65e82701dc 100644
--- a/src/main/java/fr/insarennes/nperier/minichamo/parsing/TypedefParser.java
+++ b/src/main/java/fr/insarennes/nperier/minichamo/parsing/TypedefParser.java
@@ -55,8 +55,6 @@ public class TypedefParser {
         final Set<String> lgenerics = generics.stream()
                 .map(Type::getName)
                 .collect(Collectors.toSet());
-        System.out.println(lgenerics);
-        System.out.println(rgenerics);
         Set<String> diff = lgenerics.stream()
                 .filter(s -> !rgenerics.contains(s))
                 .collect(Collectors.toSet());
diff --git a/src/test/java/fr/insarennes/nperier/minichamo/parsing/ExpressionParserTest.java b/src/test/java/fr/insarennes/nperier/minichamo/parsing/ExpressionParserTest.java
index 9999754c8516a5c1382e7138df04e3bdf3ea3cff..739d3ea51fdb5c5dd4b75bd6c5695bb189dc8cf1 100644
--- a/src/test/java/fr/insarennes/nperier/minichamo/parsing/ExpressionParserTest.java
+++ b/src/test/java/fr/insarennes/nperier/minichamo/parsing/ExpressionParserTest.java
@@ -3,13 +3,12 @@ package fr.insarennes.nperier.minichamo.parsing;
 import fr.insarennes.nperier.minichamo.errors.ParsingException;
 import fr.insarennes.nperier.minichamo.language.Context;
 import fr.insarennes.nperier.minichamo.language.definition.ValueDef;
-import fr.insarennes.nperier.minichamo.language.expressions.ConditionExpression;
-import fr.insarennes.nperier.minichamo.language.expressions.Expression;
-import fr.insarennes.nperier.minichamo.language.expressions.NameExpression;
-import fr.insarennes.nperier.minichamo.language.expressions.VarExpression;
+import fr.insarennes.nperier.minichamo.language.expressions.*;
 import fr.insarennes.nperier.minichamo.language.expressions.base.*;
 import fr.insarennes.nperier.minichamo.language.typing.BuiltinType;
 import fr.insarennes.nperier.minichamo.language.typing.GenericType;
+import fr.insarennes.nperier.minichamo.language.typing.NupleType;
+import fr.insarennes.nperier.minichamo.language.typing.Type;
 import fr.insarennes.nperier.minichamo.lexing.Lexer;
 import fr.insarennes.nperier.minichamo.lexing.tokens.TokenType;
 import fr.insarennes.nperier.minichamo.utils.SymbolPosition;
@@ -18,6 +17,8 @@ import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
+import java.util.List;
+
 public class ExpressionParserTest {
 
     private Context ctx;
@@ -127,4 +128,26 @@ public class ExpressionParserTest {
         Assertions.assertThrows(ParsingException.class, () -> ExpressionParser.parse(it, ctx));
     }
 
+    /*@Test
+    public void nupleTest() {
+        TokenPeekIterator it = new Lexer("(1, \"bonjour\", true);;").wrap();
+        Expression e = ExpressionParser.parse(it, ctx);
+        e.display();
+        Expression exp = new NupleExpression(List.of(
+                new IntExpression(1),
+                new StringExpression("bonjour"),
+                new BoolExpression(true)
+        ));
+        exp.display();
+        Type t = new NupleType(new Type[] {
+                BuiltinType.integer(),
+                BuiltinType.str(),
+                BuiltinType.bool()
+        });
+        Assertions.assertEquals(exp, e);
+        Assertions.assertEquals(t, e.getType());
+        Assertions.assertTrue(it.junkIf(TokenType.TERMINATION));
+        Assertions.assertFalse(it.hasNext());
+    }*/
+
 }
diff --git a/test.mll b/test.mll
new file mode 100644
index 0000000000000000000000000000000000000000..2a850f70762543793b2e68820548526606a7f628
--- /dev/null
+++ b/test.mll
@@ -0,0 +1,16 @@
+
+let a = 1;;
+
+let f a = a;;
+
+(* let b = f a;; *)
+
+let _c = 1.1;;
+
+type ('a, 'b) t = ('a * 'b) list;;
+
+type 'a graph =
+| Leaf of 'a
+| Node of 'a * ('a graph) list;;
+
+type int_graph = int graph;;