├── .travis.yml ├── src ├── main │ └── java │ │ └── fr │ │ └── lifl │ │ └── jaskell │ │ ├── compiler │ │ ├── core │ │ │ ├── .cvsignore │ │ │ ├── Tag.java │ │ │ ├── EmptyIterator.java │ │ │ ├── Binder.java │ │ │ ├── Binding.java │ │ │ ├── JaskellException.java │ │ │ ├── TypeTag.java │ │ │ ├── package.html │ │ │ ├── Constructor.java │ │ │ ├── Pattern.java │ │ │ ├── FileAndLineTag.java │ │ │ ├── FloatLiteral.java │ │ │ ├── CharLiteral.java │ │ │ ├── StringLiteral.java │ │ │ ├── DoubleLiteral.java │ │ │ ├── IntegerLiteral.java │ │ │ ├── Variable.java │ │ │ ├── BooleanLiteral.java │ │ │ ├── ExpressionTypeContext.java │ │ │ ├── Expression.java │ │ │ ├── Literal.java │ │ │ ├── Definition.java │ │ │ ├── QualifiedVariable.java │ │ │ ├── Conditional.java │ │ │ ├── QualifiedConstructor.java │ │ │ ├── ExpressionBase.java │ │ │ ├── PrimitiveFunction.java │ │ │ ├── Application.java │ │ │ ├── ConstructorPattern.java │ │ │ └── LocalBinding.java │ │ ├── types │ │ │ ├── Kind.java │ │ │ ├── TypeApplicationFormat.java │ │ │ ├── TypeConstraint.java │ │ │ ├── TypeVisitor.java │ │ │ ├── SimpleKind.java │ │ │ ├── TypeClass.java │ │ │ ├── package.html │ │ │ ├── UncomparableException.java │ │ │ ├── TypeError.java │ │ │ ├── FunctionKind.java │ │ │ ├── CovariantComparator.java │ │ │ ├── TypeClassConstraint.java │ │ │ ├── FunctionComparator.java │ │ │ ├── TypeSubstitution.java │ │ │ ├── TyvarCollector.java │ │ │ ├── ConstrainedType.java │ │ │ ├── TypeConstraintsBuilder.java │ │ │ ├── Visitors.java │ │ │ ├── TypeVariable.java │ │ │ ├── TypeComparator.java │ │ │ ├── TypeInstantiator.java │ │ │ ├── TypeConstraints.java │ │ │ ├── TypeConstructor.java │ │ │ ├── TypeContext.java │ │ │ ├── TypeFactory.java │ │ │ └── TypeApplication.java │ │ ├── CompilerException.java │ │ ├── package.html │ │ ├── bytecode │ │ │ ├── package.html │ │ │ └── Type2String.java │ │ ├── datatypes │ │ │ ├── package.html │ │ │ ├── PrimitiveData.java │ │ │ ├── PrimitiveConstructor.java │ │ │ └── DataDefinition.java │ │ ├── JaskellVisitor.java │ │ ├── Main.java │ │ └── CaptureCollector.java │ │ ├── parser │ │ ├── .cvsignore │ │ ├── PatternMatch.java │ │ ├── TypeExpression.java │ │ ├── package.html │ │ ├── ParseException.java │ │ ├── Equation.java │ │ ├── ExpressionList.java │ │ └── PatternAlternative.java │ │ ├── runtime │ │ ├── types │ │ │ ├── Int_2d_3eBool.java │ │ │ ├── Unit.java │ │ │ ├── JList.java │ │ │ ├── Tuple.java │ │ │ ├── JFunction.java │ │ │ ├── Tuple_3.java │ │ │ ├── JObject.java │ │ │ ├── Tuple_4.java │ │ │ ├── JEvent.java │ │ │ ├── Tuple_Int_Int.java │ │ │ ├── _5b_5d.java │ │ │ ├── JChar.java │ │ │ ├── Tuple_2.java │ │ │ ├── JInt.java │ │ │ ├── JFloat.java │ │ │ ├── JDouble.java │ │ │ ├── JBoolean.java │ │ │ ├── JString.java │ │ │ ├── JMessage.java │ │ │ ├── _3a.java │ │ │ ├── Event.java │ │ │ ├── Closure.java │ │ │ ├── JError.java │ │ │ └── JValue.java │ │ └── classes │ │ │ ├── Eq.java │ │ │ └── Monad.java │ │ └── cli │ │ └── Jaskell.java ├── test │ ├── resources │ │ └── simple.k │ └── java │ │ └── fr │ │ └── lifl │ │ └── jaskell │ │ ├── parser │ │ ├── YylexTest.java │ │ ├── NormalizerTest.java │ │ └── ParserTest.java │ │ ├── compiler │ │ ├── types │ │ │ ├── TypeInstantiatorTest.java │ │ │ ├── TypeComparatorTest.java │ │ │ ├── ConstrainedTypeTest.java │ │ │ └── TypeUnifierTest.java │ │ ├── ConstantPropagatorTest.java │ │ ├── core │ │ │ └── ModuleTest.java │ │ ├── bytecode │ │ │ └── Type2ClassTest.java │ │ ├── LambdaLifterTest.java │ │ ├── CompilerPassTest.java │ │ └── CompilerTest.java │ │ └── cli │ │ └── JaskellTest.java └── site │ ├── apt │ └── index.apt │ └── site.xml ├── test1.hs ├── verify.sh └── pom.xml /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/core/.cvsignore: -------------------------------------------------------------------------------- 1 | Let.java 2 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/parser/.cvsignore: -------------------------------------------------------------------------------- 1 | y 2 | Yylex.java 3 | Yyparser.java 4 | -------------------------------------------------------------------------------- /src/test/resources/simple.k: -------------------------------------------------------------------------------- 1 | module Main where { 2 | fac 0 = 1 ; 3 | fac n = n * fac (n - 1); 4 | 5 | main = primPutInt (fac 4) 6 | } -------------------------------------------------------------------------------- /test1.hs: -------------------------------------------------------------------------------- 1 | 2 | module Test where { 3 | 4 | data TMsg = Call | Return | Event; 5 | 6 | data DMsg = Emit | Receive 7 | 8 | 9 | } 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/types/Kind.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.compiler.types; 2 | 3 | /** 4 | * 5 | * @author bailly 6 | * @version $Id: Kind.java 1153 2005-11-24 20:47:55Z nono $ 7 | */ 8 | public interface Kind { 9 | public Kind apply(Kind kind); 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/CompilerException.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.compiler; 2 | 3 | /** 4 | * 5 | * @author bailly 6 | * @version $Id: CompilerException.java 1153 2005-11-24 20:47:55Z nono $ 7 | */ 8 | public class CompilerException extends RuntimeException { 9 | 10 | public CompilerException (String reason) { 11 | super(reason); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/runtime/types/Int_2d_3eBool.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.runtime.types; 2 | 3 | /** 4 | * A type for functions taking an int and returning a boolean 5 | * 6 | * @author bailly 7 | * @version $Id: Int_2d_3eBool.java 1153 2005-11-24 20:47:55Z nono $ 8 | * */ 9 | public interface Int_2d_3eBool extends JFunction { 10 | 11 | public boolean apply(int i); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/parser/PatternMatch.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.parser; 2 | 3 | import fr.lifl.jaskell.compiler.core.Expression; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * @author bailly 9 | * @version $Id: PatternMatch.java 1154 2005-11-24 21:43:37Z nono $ 10 | */ 11 | class PatternMatch { 12 | 13 | List patterns; 14 | 15 | Expression expr; 16 | 17 | public String toString() { 18 | return "(" + patterns.toString()+","+ expr.toString() +")"; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/runtime/classes/Eq.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.runtime.classes; 2 | 3 | /** 4 | * Base interface for types defining equality 5 | * 6 | * @author bailly 7 | * @version $Id: Eq.java 1153 2005-11-24 20:47:55Z nono $ 8 | * */ 9 | public interface Eq { 10 | 11 | /** 12 | * (==) :: a -> a -> Bool 13 | */ 14 | public boolean _3d_3d(Eq a, Eq b); 15 | 16 | /** 17 | * (/=) :: a -> a -> Bool 18 | */ 19 | public boolean _2f_3d(Eq a, Eq b); 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/runtime/types/Unit.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.runtime.types; 2 | 3 | /** 4 | * A type that does nothing and which contains only one member. 5 | * 6 | * 7 | * @author bailly 8 | * @version $Id: Unit.java 1153 2005-11-24 20:47:55Z nono $ 9 | * */ 10 | public class Unit extends JValue { 11 | 12 | public static final Unit UNIT = new Unit(); 13 | 14 | private Unit() { 15 | } 16 | 17 | /** 18 | * @see java.lang.Object#toString() 19 | */ 20 | public String toString() { 21 | return "()"; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/runtime/types/JList.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.runtime.types; 2 | 3 | /** 4 | * Abstract base class for all objects of type list. Each subclass 5 | * of lists handles a specific kind of list. 6 | * 7 | * @author bailly 8 | * @version $Id: JList.java 1153 2005-11-24 20:47:55Z nono $ 9 | * */ 10 | public abstract class JList extends JValue { 11 | 12 | public static JList _5b_5d() { 13 | return _5b_5d._instance; 14 | } 15 | 16 | public static JList _3a(JObject obj, JObject list) { 17 | return new _3a(obj, list); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/site/apt/index.apt: -------------------------------------------------------------------------------- 1 | ----- 2 | Jaskell: Java compiler for Haskell language 3 | ----- 4 | Arnaud Bailly 5 | ----- 6 | 3 December 2005 7 | ----- 8 | 9 | Introduction 10 | 11 | <> aims to be a compiler for the 12 | {{{http:://www.haskell.org} Haskell 98}} language, which is a 13 | <>, <>, <> functional language. The 14 | compiler generates 15 | {{{http://java.sun.com/docs/books/vmspec/2nd-edition/html/Instructions.doc.html} 16 | Java bytecode}} instructions and structure everything as Java classes which may be embedded 17 | with standard Java language constructs. 18 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/types/TypeApplicationFormat.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.compiler.types; 2 | 3 | /** 4 | * An interface that is used by TypeApplication to format 5 | * properly type applications 6 | * 7 | * @author bailly 8 | * @version $Id: TypeApplicationFormat.java 1153 2005-11-24 20:47:55Z nono $ 9 | */ 10 | public interface TypeApplicationFormat { 11 | 12 | /** 13 | * Format application of dom to range 14 | * 15 | * @param dom a Type 16 | * @param range a Type 17 | * @return string representation of this applicatino 18 | */ 19 | String formatApply(Type dom,Type range); 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/runtime/types/Tuple.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.runtime.types; 2 | 3 | /** 4 | * This class is the super class of all tuple objects. 5 | * 6 | * The Tuple class is an abstract class which only stores 7 | * the size of the tuple. Concrete subclass must be created for 8 | * each type instance. 9 | * 10 | * @author bailly 11 | * @version $Id: Tuple.java 1153 2005-11-24 20:47:55Z nono $ 12 | * */ 13 | public abstract class Tuple extends JValue { 14 | 15 | /** size of tuple */ 16 | private int size; 17 | 18 | protected Tuple(int sz) { 19 | this.size = sz; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/types/TypeConstraint.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.compiler.types; 2 | 3 | import java.util.Map; 4 | import java.util.Set; 5 | 6 | public interface TypeConstraint { 7 | boolean containsVariable(TypeVariable variableType); 8 | 9 | void collectTo(Set constraints); 10 | 11 | /** 12 | * Applies a mapping to this constraint replacing all occurrences of mapped type by their image. 13 | * 14 | * 15 | * @param map a substitution from Types to Types 16 | * @return an updated TypeConstraint 17 | */ 18 | TypeConstraint substitute(TypeSubstitution map); 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/runtime/types/JFunction.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.runtime.types; 2 | 3 | /** 4 | * Base interface for function objects 5 | * 6 | * @author bailly 7 | * @version $Id: JFunction.java 1153 2005-11-24 20:47:55Z nono $ 8 | */ 9 | public interface JFunction extends JObject { 10 | 11 | /** 12 | * Partial application of arguments 13 | * 14 | * @param obj a JObject 15 | * @return a JObject 16 | */ 17 | public JObject apply(JObject obj); 18 | 19 | /** 20 | * Create a new instance of this function 21 | * 22 | * @return a copy of this function 23 | */ 24 | public JFunction init(); 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/runtime/types/Tuple_3.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.runtime.types; 2 | 3 | /** 4 | * A generic class for 3-tuples. 5 | * 6 | * @author bailly 7 | * @version $Id: Tuple_3.java 1153 2005-11-24 20:47:55Z nono $ 8 | * */ 9 | public class Tuple_3 extends Tuple { 10 | 11 | private JObject fst,snd,thd; 12 | 13 | /** 14 | * Unboxed - generic - constructor for 3-tuples 15 | * 16 | */ 17 | protected Tuple_3() { 18 | super(3); 19 | } 20 | 21 | /** 22 | * Boxed constructor for Tuple_3. 23 | * @param sz 24 | */ 25 | public Tuple_3(JObject a, JObject b,JObject c) { 26 | super(3); 27 | fst = a; 28 | snd = b; 29 | thd = c; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/types/TypeVisitor.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.compiler.types; 2 | 3 | import java.util.logging.Logger; 4 | 5 | 6 | /** 7 | * An interface to visit type constructs 8 | * 9 | * @author bailly 10 | * @version $Id: TypeVisitor.java 1153 2005-11-24 20:47:55Z nono $ 11 | * */ 12 | public interface TypeVisitor { 13 | 14 | public static final Logger log = Logger.getLogger(TypeVisitor.class.getName()); 15 | 16 | T visit(TypeVariable t); 17 | 18 | T visit(PrimitiveType primitiveType); 19 | 20 | T visit(TypeApplication typeApplication); 21 | 22 | T visit(TypeConstructor typeConstructor); 23 | 24 | T visit(ConstrainedType constrainedType); 25 | } 26 | -------------------------------------------------------------------------------- /src/site/site.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | 11 | http://maven.apache.org/images/maven-small.gif 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | ${reports} 24 | 25 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/core/Tag.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on Jun 9, 2003 3 | * Copyright 2003 Arnaud Bailly 4 | */ 5 | package fr.lifl.jaskell.compiler.core; 6 | 7 | /** 8 | * Tag instances are used to annotate the abstract syntax tree with 9 | * semantic information like strictness status or type. 10 | * 11 | * @author bailly 12 | * @version $Id: Tag.java 1153 2005-11-24 20:47:55Z nono $ 13 | */ 14 | public interface Tag { 15 | 16 | /** 17 | * Returns the name identifying this tag. A name must 18 | * be unique among all tags stored in a node as it is used 19 | * as a key to a hashtable. 20 | * 21 | * @return 22 | */ 23 | public String getName(); 24 | 25 | 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/runtime/types/JObject.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.runtime.types; 2 | 3 | /** 4 | * The root class for all objects manipulated in Jaskell. 5 | * 6 | * All objects manipulated in Jaskell derives from this base class. 7 | * 8 | * @author bailly 9 | * @version $Id: JObject.java 1153 2005-11-24 20:47:55Z nono $ 10 | * */ 11 | public interface JObject { 12 | /** 13 | * Evaluates this objects, yielding a supposedly reduced 14 | * object. The implementation iin JObject does nothing and 15 | * returns this. 16 | * 17 | * @return a JObject which is guaranteed to be the same object 18 | * or a reduced form of this. 19 | */ 20 | public JObject eval(); 21 | 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/runtime/types/Tuple_4.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.runtime.types; 2 | 3 | /** 4 | * A generic class for 4-tuples. 5 | * 6 | * @author bailly 7 | * @version $Id: Tuple_4.java 1153 2005-11-24 20:47:55Z nono $ 8 | * */ 9 | public class Tuple_4 extends Tuple { 10 | 11 | private JObject fst,snd,thd,fth; 12 | 13 | /** 14 | * Unboxed - generic - constructor for 4-tuples 15 | * 16 | */ 17 | protected Tuple_4() { 18 | super(4); 19 | } 20 | 21 | /** 22 | * Boxed constructor for Tuple_2. 23 | * @param sz 24 | */ 25 | public Tuple_4(JObject a, JObject b,JObject c, JObject d) { 26 | super(4); 27 | fst = a; 28 | snd = b; 29 | thd = c; 30 | fth = d; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/core/EmptyIterator.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.compiler.core; 2 | 3 | import java.util.Iterator; 4 | import java.util.NoSuchElementException; 5 | 6 | /** 7 | * An empty iterator class. 8 | * 9 | * @author bailly 10 | * @version $Id: EmptyIterator.java 1153 2005-11-24 20:47:55Z nono $ 11 | * */ 12 | class EmptyIterator implements Iterator { 13 | 14 | public boolean hasNext() { 15 | return false; 16 | } 17 | 18 | public Object next() { 19 | throw new NoSuchElementException("Cannot retrieve elements from an empty iterator"); 20 | } 21 | 22 | public void remove() { 23 | throw new UnsupportedOperationException("Cannot remove elements from an empty iterator"); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/runtime/classes/Monad.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.runtime.classes; 2 | 3 | import fr.lifl.jaskell.runtime.types.Closure; 4 | import fr.lifl.jaskell.runtime.types.JObject; 5 | 6 | /** 7 | * @author bailly 8 | * @version $Id: Monad.java 1154 2005-11-24 21:43:37Z nono $ 9 | * */ 10 | public interface Monad { 11 | 12 | /** 13 | * return :: a -> m a 14 | */ 15 | public Monad _return(JObject obj); 16 | 17 | /** 18 | * (>>=) :: m a -> ( a -> m b) -> m b 19 | */ 20 | public Monad _3c_3c_3d(Monad m, Closure mon); 21 | 22 | /** 23 | * (>>) :: m a -> m b -> m b 24 | */ 25 | public Monad _3c_3c(Monad ma, Monad mb); 26 | 27 | /** 28 | * fail :: String -> m a 29 | */ 30 | public Monad fail(String s); 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/runtime/types/JEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on Jul 1, 2004 3 | * 4 | */ 5 | package fr.lifl.jaskell.runtime.types; 6 | 7 | /** 8 | * Type for Events 9 | * 10 | * @author nono 11 | * @version $Id: JEvent.java 1153 2005-11-24 20:47:55Z nono $ 12 | */ 13 | public abstract class JEvent extends JValue { 14 | 15 | } 16 | 17 | /* 18 | * $Log: JEvent.java,v $ 19 | * Revision 1.1 2004/07/01 15:57:41 bailly 20 | * suppression de l'interface Namespace au profit de fr.lifl.parsing.Namespace 21 | * modification de la g?n?ration de code pour les constructeurs et les types de donnees 22 | * creation d'un type JEvent et d'un constructeur Event 23 | * modification du parser pour creer des Event lors de l'analyse syntaxique 24 | * 25 | */ -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/parser/TypeExpression.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.parser; 2 | 3 | import fr.lifl.jaskell.compiler.core.ExpressionBase; 4 | import fr.lifl.jaskell.compiler.types.Type; 5 | 6 | /** 7 | * @author bailly 8 | * @version $Id: TypeExpression.java 1154 2005-11-24 21:43:37Z nono $ 9 | */ 10 | public class TypeExpression extends ExpressionBase { 11 | 12 | private boolean strict; 13 | 14 | /** 15 | * Constructor for TypeDefinition. 16 | */ 17 | public TypeExpression(Type type) { 18 | setType(type); 19 | } 20 | 21 | 22 | /** 23 | * @return 24 | */ 25 | public boolean isStrict() { 26 | return strict; 27 | } 28 | 29 | /** 30 | * @param b 31 | */ 32 | public void setStrict(boolean b) { 33 | strict = b; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/test/java/fr/lifl/jaskell/parser/YylexTest.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.parser; 2 | import junit.framework.TestCase; 3 | 4 | /** 5 | * @author bailly 6 | * @version $Id: YylexTest.java 1183 2005-12-07 22:45:19Z nono $ 7 | */ 8 | public class YylexTest extends TestCase { 9 | 10 | /** 11 | * Constructor for YylexTest. 12 | * @param arg0 13 | */ 14 | public YylexTest(String arg0) { 15 | super(arg0); 16 | } 17 | 18 | public void testYylex1() throws Exception { 19 | String data = "module where Huiui.h = 0737 => 0x34 \"hkjhk \" 'k' ;"; 20 | java.io.Reader rd = new java.io.StringReader(data); 21 | Yylex lex = new Yylex(rd); 22 | lex.parser = new Yyparser(); 23 | int tok; 24 | while ((tok = lex.yylex()) > 0) 25 | System.err.println(Yyparser.yyname[tok]); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/types/SimpleKind.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.compiler.types; 2 | 3 | /** 4 | * 5 | * @author bailly 6 | * @version $Id: SimpleKind.java 1153 2005-11-24 20:47:55Z nono $ 7 | */ 8 | public class SimpleKind implements Kind { 9 | 10 | /* the one and only instance of SimpleKind */ 11 | public static final SimpleKind K = new SimpleKind(); 12 | 13 | /* constructor is made private to prevent construction of 14 | * other simple kind 15 | */ 16 | private SimpleKind() {} 17 | 18 | /** 19 | * @see java.lang.Object#toString() 20 | */ 21 | public String toString() { 22 | return "*"; 23 | } 24 | 25 | /** 26 | * @see jaskell.compiler.types.Kind#apply(Kind) 27 | */ 28 | public Kind apply(Kind kind) { 29 | throw new TypeError("Invalid appllication to kind *"); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/core/Binder.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.compiler.core; 2 | 3 | /** 4 | * An interface for expressions that bind variables 5 | * 6 | * This interface is implemented by expressions which bind variables. It is mainly used 7 | * to do strictness analysis and retrieve parameters by positions 8 | * 9 | * @author bailly 10 | * @version $Id: Binder.java 1153 2005-11-24 20:47:55Z nono $ 11 | */ 12 | public interface Binder { 13 | 14 | /** 15 | * Returns the strictness status of a parameter 16 | * given by its index 17 | * 18 | * @param i index of parameter 19 | */ 20 | public boolean isStrict(int i); 21 | 22 | /** 23 | * Sets the strictness status of paremeter given by name 24 | * 25 | * @param s the name of variable to set strict 26 | */ 27 | public void setStrict(String s); 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/package.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 20 | 21 | 22 | A package containing compiler API. 23 | 24 |

Package Specification

25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/parser/package.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 20 | 21 | 22 | A package that contains parsing specific classes. 23 | 24 |

Package Specification

25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/core/Binding.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.compiler.core; 2 | 3 | import fr.lifl.jaskell.compiler.types.Type; 4 | 5 | /** 6 | * This interface is implemented by all name to objects bindings. 7 | * 8 | * @author bailly 9 | * @version $Id: Binding.java 1154 2005-11-24 21:43:37Z nono $ 10 | * */ 11 | public interface Binding { 12 | 13 | /** 14 | * Returns the name. 15 | * @return String 16 | */ 17 | public String getName() ; 18 | 19 | /** 20 | * Returns the type. 21 | * @return Type 22 | */ 23 | public Type getType() ; 24 | 25 | /** 26 | * Returns the strictness status of this bindings 27 | * 28 | * @return true is this binding is strict, false otherwise 29 | */ 30 | public boolean isStrict(); 31 | 32 | /** 33 | * Method getDefinition. 34 | * @return Expression 35 | */ 36 | Expression getDefinition(); 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/types/TypeClass.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.compiler.types; 2 | 3 | public class TypeClass { 4 | private final String className; 5 | 6 | public TypeClass(String className) { 7 | this.className = className; 8 | } 9 | 10 | @Override 11 | public String toString() { 12 | return className; 13 | } 14 | 15 | @Override 16 | public boolean equals(Object o) { 17 | if (this == o) return true; 18 | if (o == null || getClass() != o.getClass()) return false; 19 | 20 | TypeClass typeClass = (TypeClass) o; 21 | 22 | if (className != null ? !className.equals(typeClass.className) : typeClass.className != null) return false; 23 | 24 | return true; 25 | } 26 | 27 | @Override 28 | public int hashCode() { 29 | return className != null ? className.hashCode() : 0; 30 | } 31 | } -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/bytecode/package.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 20 | 21 | 22 | A package containing Java-bytecode specific classes. 23 | 24 |

Package Specification

25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /verify.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # iterate over directories 4 | 5 | while [ $# -gt 0 ] 6 | do 7 | i="$1" 8 | # compute list of classes 9 | flist=`find $i -name \*.class` 10 | # iterate over classes 11 | for f in $flist; do 12 | cname=`expr $f : '\(.*\).class'` 13 | echo -n "Verifying $cname ..." 14 | if java -verify -cp $i/..:../jaskell/bin $cname > /tmp/jout 2>&1 ; then 15 | echo "OK" 16 | elif grep "java.lang.NoSuchMethodError: main" /tmp/jout > /dev/null 2>&1; then 17 | echo "OK" 18 | else 19 | echo "KO" 20 | echo "======= Class $cname =======" >> /tmp/jerr 21 | cat /tmp/jout >> /tmp/jerr 22 | fi 23 | done 24 | shift 25 | done 26 | 27 | if [ -f /tmp/jerr ]; then 28 | echo "Errors found, outputing verifier diagnostic :" 29 | cat /tmp/jerr 30 | fi 31 | 32 | # clenaup 33 | [ -f /tmp/jout ] && rm /tmp/jout 34 | [ -f /tmp/jerr ] && rm /tmp/jerr 35 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/parser/ParseException.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.parser; 2 | 3 | /** 4 | * @author bailly 5 | * @version $Id: ParseException.java 1153 2005-11-24 20:47:55Z nono $ 6 | */ 7 | public class ParseException extends RuntimeException { 8 | 9 | /** 10 | * Constructor for ParseException. 11 | */ 12 | public ParseException() { 13 | super(); 14 | } 15 | 16 | /** 17 | * Constructor for ParseException. 18 | * @param message 19 | */ 20 | public ParseException(String message) { 21 | super(message); 22 | } 23 | 24 | /** 25 | * Constructor for ParseException. 26 | * @param message 27 | * @param cause 28 | */ 29 | public ParseException(String message, Throwable cause) { 30 | super(message, cause); 31 | } 32 | 33 | /** 34 | * Constructor for ParseException. 35 | * @param cause 36 | */ 37 | public ParseException(Throwable cause) { 38 | super(cause); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/types/package.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 20 | 21 | 22 | This package contains classes and interfaces to describe type expressions in Jaskell. 23 | 24 |

Package Specification

25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/runtime/types/Tuple_Int_Int.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.runtime.types; 2 | 3 | /** 4 | * @author bailly 5 | * @version $Id: Tuple_Int_Int.java 1153 2005-11-24 20:47:55Z nono $ 6 | * */ 7 | public class Tuple_Int_Int extends Tuple_2 { 8 | 9 | private int i1,i2; 10 | 11 | public Tuple_Int_Int(int a,int b) { 12 | this.i1 = a; 13 | this.i2 = b; 14 | } 15 | 16 | public Tuple_Int_Int(JInt a,JInt b) { 17 | super(a,b); 18 | } 19 | 20 | 21 | public JObject fst() { 22 | return new JInt(i1); 23 | } 24 | 25 | public JObject snd() { 26 | return new JInt(i2); 27 | } 28 | 29 | /** 30 | * Unboxed first projection 31 | * 32 | * @return an int 33 | */ 34 | public int fst_int() { 35 | return i1; 36 | } 37 | 38 | /** 39 | * Unboxed second projection 40 | * 41 | * @return an int 42 | */ 43 | public int snd_int() { 44 | return i2; 45 | } 46 | 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/datatypes/package.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 20 | 21 | 22 | This package contains classes that store definitions of type constructs in Jaskell : algebraic data types, 23 | type classes, classes instances, ... 24 | 25 |

Package Specification

26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/runtime/types/_5b_5d.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on Jun 4, 2003 by Arnaud Bailly - bailly@lifl.fr 3 | * Copyright 2003 - Arnaud Bailly 4 | */ 5 | package fr.lifl.jaskell.runtime.types; 6 | 7 | 8 | /** a private class for handling the nil constant */ 9 | public class _5b_5d extends JList implements JFunction { 10 | 11 | /** The nil object */ 12 | static public final JList _instance = new _5b_5d(); 13 | 14 | public _5b_5d() {} 15 | 16 | /* (non-Javadoc) 17 | * @see jaskell.runtime.types.JFunction#apply(jaskell.runtime.types.JObject) 18 | */ 19 | public JObject apply(JObject obj) { 20 | throw new JError("Invalid application of "+obj +" to Cons"); 21 | } 22 | 23 | 24 | /* (non-Javadoc) 25 | * @see jaskell.runtime.types.JFunction#init() 26 | */ 27 | public JFunction init() { 28 | return (JFunction)_instance; 29 | } 30 | 31 | /* (non-Javadoc) 32 | * @see java.lang.Object#toString() 33 | */ 34 | public String toString() { 35 | return "[]"; 36 | } 37 | 38 | } -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/runtime/types/JChar.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.runtime.types; 2 | 3 | /** 4 | * Wrapper class for char values 5 | * 6 | * @author bailly 7 | * @version $Id: JChar.java 1153 2005-11-24 20:47:55Z nono $ 8 | * */ 9 | public class JChar extends JValue { 10 | 11 | /** the char contained in this JInt */ 12 | private char f; 13 | 14 | /** 15 | * constructs a Jchar from a char 16 | * 17 | * @param f a char 18 | */ 19 | public JChar(char f) { 20 | this.f = f; 21 | } 22 | 23 | 24 | /** 25 | * @see jaskell.runtime.modules.types.JObject#evalAsChar() 26 | */ 27 | public char asChar() { 28 | return f; 29 | } 30 | /* (non-Javadoc) 31 | * @see java.lang.Object#toString() 32 | */ 33 | public String toString() { 34 | return ""+f; 35 | } 36 | 37 | /* (non-Javadoc) 38 | * @see java.lang.Object#equals(java.lang.Object) 39 | */ 40 | public boolean equals(Object obj) { 41 | if(obj == null) 42 | return false; 43 | JChar jchar = (JChar)obj; 44 | return jchar.f == f; 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/runtime/types/Tuple_2.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.runtime.types; 2 | 3 | /** 4 | * A generic class for 2-tuples. 5 | * 6 | * @author bailly 7 | * @version $Id: Tuple_2.java 1153 2005-11-24 20:47:55Z nono $ 8 | * */ 9 | public class Tuple_2 extends Tuple { 10 | 11 | private JObject fst,snd; 12 | 13 | /** 14 | * Unboxed - generic - constructor for two tuples 15 | * 16 | */ 17 | protected Tuple_2() { 18 | super(2); 19 | } 20 | 21 | /** 22 | * Boxed constructor for Tuple_2. 23 | * @param sz 24 | */ 25 | public Tuple_2(JObject a, JObject b) { 26 | super(2); 27 | fst = a; 28 | snd = b; 29 | } 30 | 31 | /** 32 | * Return boxed first component of tuple 33 | * 34 | * @return a JObject representing first component 35 | */ 36 | public JObject fst() { 37 | return fst; 38 | } 39 | 40 | /** 41 | * Return boxed seconde component of tuple 42 | * 43 | * @return a JObject representing second component 44 | */ 45 | public JObject snd() { 46 | return snd; 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/runtime/types/JInt.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.runtime.types; 2 | 3 | /** 4 | * Wrapper class for int values 5 | * 6 | * @author bailly 7 | * @version $Id: JInt.java 1153 2005-11-24 20:47:55Z nono $ 8 | * */ 9 | public class JInt extends JValue { 10 | 11 | /** the integer contained in this JInt */ 12 | private int i; 13 | 14 | /** 15 | * constructs a JInt from an int 16 | * 17 | * @param i an integer 18 | */ 19 | public JInt(int i) { 20 | this.i = i; 21 | } 22 | 23 | /** 24 | * @see jaskell.runtime.modules.types.JObject#evalAsInt() 25 | */ 26 | public int asInt() { 27 | return i; 28 | } 29 | 30 | 31 | 32 | /* (non-Javadoc) 33 | * @see java.lang.Object#toString() 34 | */ 35 | public String toString() { 36 | return ""+i; 37 | } 38 | 39 | /* (non-Javadoc) 40 | * @see java.lang.Object#equals(java.lang.Object) 41 | */ 42 | public boolean equals(Object obj) { 43 | if(obj == null) 44 | return false; 45 | JInt jint = (JInt)obj; 46 | return jint.i == i; 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/runtime/types/JFloat.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.runtime.types; 2 | 3 | /** 4 | * Wrapper class for float values 5 | * 6 | * @author bailly 7 | * @version $Id: JFloat.java 1153 2005-11-24 20:47:55Z nono $ 8 | * */ 9 | public class JFloat extends JValue { 10 | 11 | /** the float contained in this JInt */ 12 | private float f; 13 | 14 | /** 15 | * constructs a JFloat from a float 16 | * 17 | * @param f a float 18 | */ 19 | public JFloat(float f) { 20 | this.f = f; 21 | } 22 | 23 | 24 | /** 25 | * @see jaskell.runtime.modules.types.JObject#evalAsFloat() 26 | */ 27 | public float asFloat() { 28 | return f; 29 | } 30 | /* (non-Javadoc) 31 | * @see java.lang.Object#toString() 32 | */ 33 | public String toString() { 34 | return ""+f; 35 | } 36 | 37 | /* (non-Javadoc) 38 | * @see java.lang.Object#equals(java.lang.Object) 39 | */ 40 | public boolean equals(Object obj) { 41 | if(obj == null) 42 | return false; 43 | JFloat jfloat = (JFloat)obj; 44 | return jfloat.f == f; 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/core/JaskellException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on Jun 9, 2003 3 | * Copyright 2003 Arnaud Bailly 4 | */ 5 | package fr.lifl.jaskell.compiler.core; 6 | 7 | /** 8 | * @author bailly 9 | * @version $Id: JaskellException.java 1153 2005-11-24 20:47:55Z nono $ 10 | */ 11 | public class JaskellException extends RuntimeException { 12 | 13 | /** 14 | * 15 | */ 16 | public JaskellException() { 17 | super(); 18 | // TODO Auto-generated constructor stub 19 | } 20 | 21 | /** 22 | * @param message 23 | */ 24 | public JaskellException(String message) { 25 | super(message); 26 | // TODO Auto-generated constructor stub 27 | } 28 | 29 | /** 30 | * @param message 31 | * @param cause 32 | */ 33 | public JaskellException(String message, Throwable cause) { 34 | super(message, cause); 35 | // TODO Auto-generated constructor stub 36 | } 37 | 38 | /** 39 | * @param cause 40 | */ 41 | public JaskellException(Throwable cause) { 42 | super(cause); 43 | // TODO Auto-generated constructor stub 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/runtime/types/JDouble.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.runtime.types; 2 | 3 | /** 4 | * Wrapper class for double values 5 | * 6 | * @author bailly 7 | * @version $Id: JDouble.java 1153 2005-11-24 20:47:55Z nono $ 8 | * */ 9 | public class JDouble extends JValue { 10 | 11 | /** the double contained in this JInt */ 12 | private double f; 13 | 14 | /** 15 | * constructs a Jdouble from a double 16 | * 17 | * @param f a double 18 | */ 19 | public JDouble(double f) { 20 | this.f = f; 21 | } 22 | 23 | 24 | /** 25 | * @see jaskell.runtime.modules.types.JObject#evalAsDouble() 26 | */ 27 | public double asDouble() { 28 | return f; 29 | } 30 | /* (non-Javadoc) 31 | * @see java.lang.Object#toString() 32 | */ 33 | public String toString() { 34 | return ""+f; 35 | } 36 | 37 | /* (non-Javadoc) 38 | * @see java.lang.Object#equals(java.lang.Object) 39 | */ 40 | public boolean equals(Object obj) { 41 | if(obj == null) 42 | return false; 43 | JDouble jdouble = (JDouble)obj; 44 | return jdouble.f == f; 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/datatypes/PrimitiveData.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.compiler.datatypes; 2 | 3 | import fr.lifl.jaskell.compiler.JaskellVisitor; 4 | import fr.lifl.jaskell.compiler.core.Module; 5 | import fr.lifl.jaskell.compiler.types.Type; 6 | 7 | /** 8 | * @author bailly 9 | * @version $Id: PrimitiveData.java 1154 2005-11-24 21:43:37Z nono $ 10 | */ 11 | public class PrimitiveData extends DataDefinition { 12 | 13 | /** java class for this type */ 14 | private Class klass; 15 | 16 | /** 17 | * Constructor for PrimitiveData. 18 | * @param name 19 | * @param mod 20 | */ 21 | public PrimitiveData(String name, Type type,Class cls,Module module) { 22 | super(name, type,module); 23 | this.klass = cls; 24 | } 25 | 26 | /** 27 | * Returns the klass. 28 | * @return Class 29 | */ 30 | public Class getKlass() { 31 | return klass; 32 | } 33 | 34 | /* (non-Javadoc) 35 | * @see jaskell.compiler.core.Expression#visit(jaskell.compiler.JaskellVisitor) 36 | */ 37 | public Object visit(JaskellVisitor v) { 38 | return v.visit(this); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/runtime/types/JBoolean.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.runtime.types; 2 | 3 | /** 4 | * Wrapper class for boolean values 5 | * 6 | * @author bailly 7 | * @version $Id: JBoolean.java 1153 2005-11-24 20:47:55Z nono $ 8 | * */ 9 | public class JBoolean extends JValue { 10 | 11 | /** the boolean contained in this JInt */ 12 | private boolean f; 13 | 14 | /** 15 | * constructs a Jboolean from a boolean 16 | * 17 | * @param f a boolean 18 | */ 19 | public JBoolean(boolean f) { 20 | this.f = f; 21 | } 22 | 23 | 24 | /** 25 | * @see jaskell.runtime.modules.JFloat.javatypes.JObject#evalAsBoolean() 26 | */ 27 | public boolean asBool() { 28 | return f; 29 | } 30 | 31 | /* (non-Javadoc) 32 | * @see java.lang.Object#toString() 33 | */ 34 | public String toString() { 35 | return ""+f; 36 | } 37 | 38 | /* (non-Javadoc) 39 | * @see java.lang.Object#equals(java.lang.Object) 40 | */ 41 | public boolean equals(Object obj) { 42 | if(obj == null) 43 | return false; 44 | JBoolean jbo = (JBoolean)obj; 45 | return jbo.f == f; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/runtime/types/JString.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.runtime.types; 2 | 3 | /** 4 | * Wrapper class for String values 5 | * 6 | * @author bailly 7 | * @version $Id: JString.java 1153 2005-11-24 20:47:55Z nono $ 8 | * */ 9 | public class JString extends JValue { 10 | 11 | /** the String contained in this JInt */ 12 | private java.lang.String f; 13 | 14 | /** 15 | * constructs a JString from a String 16 | * 17 | * @param f a String 18 | */ 19 | public JString(java.lang.String f) { 20 | this.f = f; 21 | } 22 | 23 | 24 | /** 25 | * @see jaskell.runtime.modules.types.JObject#evalAsString() 26 | */ 27 | public java.lang.String asString() { 28 | return f; 29 | } 30 | 31 | /* (non-Javadoc) 32 | * @see java.lang.Object#toString() 33 | */ 34 | public String toString() { 35 | return '"' + f + '"'; 36 | } 37 | 38 | /* (non-Javadoc) 39 | * @see java.lang.Object#equals(java.lang.Object) 40 | */ 41 | public boolean equals(Object obj) { 42 | if(obj == null) 43 | return false; 44 | JString js = (JString)obj; 45 | return js.f.equals(f); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/core/TypeTag.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on Jun 9, 2003 3 | * Copyright 2003 Arnaud Bailly 4 | */ 5 | package fr.lifl.jaskell.compiler.core; 6 | 7 | import fr.lifl.jaskell.compiler.types.Type; 8 | 9 | /** 10 | * This tag implementation is used to store the type of an 11 | * expression. 12 | * 13 | * @author bailly 14 | * @version $Id: TypeTag.java 1154 2005-11-24 21:43:37Z nono $ 15 | */ 16 | public class TypeTag implements Tag { 17 | 18 | private static final String tagname = "type"; 19 | 20 | private Type type; 21 | 22 | /** 23 | * 24 | */ 25 | public TypeTag(Type type) { 26 | this.type = type; 27 | } 28 | 29 | /* (non-Javadoc) 30 | * @see jaskell.compiler.core.Tag#getName() 31 | */ 32 | public String getName() { 33 | return tagname; 34 | } 35 | 36 | /** 37 | * Returns the type stored in this tag 38 | * @return a Type instance 39 | */ 40 | public Type getType() { 41 | return type; 42 | } 43 | 44 | /** 45 | * Sets the type stored in this tag 46 | * @param type a Type instance 47 | */ 48 | public void setType(Type type) { 49 | this.type = type; 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/types/UncomparableException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on Mar 9, 2004 3 | * 4 | * $Log: UncomparableException.java,v $ 5 | * Revision 1.1 2004/03/10 20:31:56 bailly 6 | * added type comparison classes 7 | * 8 | */ 9 | package fr.lifl.jaskell.compiler.types; 10 | 11 | /** 12 | * This exception is thrown by @see{PartialComparator} implementations to 13 | * notify caller that the compared objects are indeed uncomparable. 14 | * 15 | * @author bailly 16 | * @version $Id: UncomparableException.java 1153 2005-11-24 20:47:55Z nono $ 17 | */ 18 | public class UncomparableException extends Exception { 19 | 20 | /** 21 | * 22 | */ 23 | public UncomparableException() { 24 | super(); 25 | } 26 | 27 | /** 28 | * @param message 29 | */ 30 | public UncomparableException(String message) { 31 | super(message); 32 | } 33 | 34 | /** 35 | * @param cause 36 | */ 37 | public UncomparableException(Throwable cause) { 38 | super(cause); 39 | } 40 | 41 | /** 42 | * @param message 43 | * @param cause 44 | */ 45 | public UncomparableException(String message, Throwable cause) { 46 | super(message, cause); 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/types/TypeError.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.compiler.types; 2 | 3 | import fr.lifl.jaskell.compiler.core.Tag; 4 | 5 | /** 6 | * @author abailly 7 | * @version $Id: TypeError.java 1154 2005-11-24 21:43:37Z nono $ 8 | */ 9 | public class TypeError extends RuntimeException { 10 | 11 | private Tag tag; 12 | 13 | /** 14 | * Constructor for TypeError. 15 | */ 16 | public TypeError() { 17 | super(); 18 | } 19 | 20 | /** 21 | * Constructor for TypeError. 22 | * @param message 23 | */ 24 | public TypeError(String message) { 25 | super(message); 26 | } 27 | 28 | /** 29 | * Constructor for TypeError. 30 | * @param message 31 | * @param cause 32 | */ 33 | public TypeError(String message, Throwable cause) { 34 | super(message, cause); 35 | } 36 | 37 | /** 38 | * Constructor for TypeError. 39 | * @param cause 40 | */ 41 | public TypeError(Throwable cause) { 42 | super(cause); 43 | } 44 | 45 | /** 46 | * @param tag 47 | */ 48 | public void setLineCol(Tag tag) { 49 | this.tag = tag; 50 | } 51 | 52 | public Tag getLineCol() { 53 | return tag; 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/runtime/types/JMessage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on Feb 23, 2004 3 | * 4 | */ 5 | package fr.lifl.jaskell.runtime.types; 6 | 7 | /** 8 | * This type represents Message objects 9 | *

10 | * The JMessage type is an internal type used by Jaskell to represnet 11 | * message objects. 12 | * 13 | * @author nono 14 | * @version $Log: JMessage.java,v $ 15 | * @version Revision 1.3 2004/07/01 15:57:41 bailly 16 | * @version suppression de l'interface Namespace au profit de fr.lifl.parsing.Namespace 17 | * @version modification de la g?n?ration de code pour les constructeurs et les types de donnees 18 | * @version creation d'un type JEvent et d'un constructeur Event 19 | * @version modification du parser pour creer des Event lors de l'analyse syntaxique 20 | * @version 21 | * @version Revision 1.2 2004/06/29 15:25:26 bailly 22 | * @version modification des types pour les messages 23 | * @version 24 | * @version Revision 1.1 2004/02/23 16:46:25 bailly 25 | * @version Added generation of MessagePattern from grammar 26 | * @version Fixed constant propagation -> methods are properly 27 | * @version resolved and called if they exist 28 | * @version 29 | */ 30 | public abstract class JMessage extends JValue { 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/core/package.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 20 | 21 | 22 | This package contains all necessary definitions for core constructs 23 | of the Jaskell language. 24 | 25 |

Package Specification

26 | During the parsing phase, the Jaskell compiler translates all high-level 27 | syntactic constructs to a lowwer-level language named Jaskell-Core which 28 | contains only a limited set of features. In particular, Jaskell-Core does not 29 | allows nested declarations and all let constructs are lifted to the module 30 | level.

31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /src/test/java/fr/lifl/jaskell/compiler/types/TypeInstantiatorTest.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.compiler.types; 2 | import junit.framework.TestCase; 3 | 4 | /** 5 | * @author bailly 6 | * @version $Id: TypeInstantiatorTest.java 1183 2005-12-07 22:45:19Z nono $ 7 | */ 8 | public class TypeInstantiatorTest extends TestCase { 9 | public static final PrimitiveType FUNCTION = 10 | new PrimitiveType( 11 | "(->)", 12 | fr.lifl.jaskell.runtime.types.Closure.class, 13 | new FunctionKind(SimpleKind.K, FunctionKind.K_K), 14 | new TypeApplicationFormat() { 15 | public String formatApply(Type d, Type r) { 16 | return r + " ->"; 17 | } 18 | }, new FunctionComparator()); 19 | 20 | /** 21 | * Constructor for TypeInstantiatorTest. 22 | * @param arg0 23 | */ 24 | public TypeInstantiatorTest(String arg0) { 25 | super(arg0); 26 | } 27 | 28 | public void test01() { 29 | Type v = TypeFactory.freshBinding(); 30 | Type v2 = TypeFactory.freshBinding(); 31 | Type t1 = 32 | Types.apply( 33 | Types.apply(FUNCTION, v), 34 | v2); 35 | /* apply instance */ 36 | Type t = new TypeInstantiator(t1).instance(); 37 | System.err.println( 38 | "susbt " + t1.makeString() + " to " + t.makeString()); 39 | assertTrue(!t.equals(t1)); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/runtime/types/_3a.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on Jun 4, 2003 by Arnaud Bailly - bailly@lifl.fr 3 | * Copyright 2003 - Arnaud Bailly 4 | */ 5 | package fr.lifl.jaskell.runtime.types; 6 | 7 | /** 8 | * @author bailly 9 | * @version $Id: _3a.java 1153 2005-11-24 20:47:55Z nono $ 10 | */ 11 | public class _3a extends JList implements JFunction { 12 | 13 | public JObject _0; 14 | 15 | public JObject _1; 16 | 17 | int _nargs; 18 | 19 | public _3a(JObject obj,JObject list) { 20 | this._0 = obj; 21 | this._1 = list; 22 | this._nargs = 2; 23 | } 24 | 25 | public _3a() { 26 | } 27 | 28 | /* (non-Javadoc) 29 | * @see jaskell.runtime.types.JFunction#apply(jaskell.runtime.types.JObject) 30 | */ 31 | public JObject apply(JObject obj) { 32 | if(this._nargs == 2) 33 | throw new JError("Invalid application of "+obj +" to Cons"); 34 | switch(this._nargs++) { 35 | case 0: 36 | _0 = obj; 37 | break; 38 | case 1: 39 | _1 = obj; 40 | break; 41 | } 42 | return this; 43 | } 44 | 45 | /* (non-Javadoc) 46 | * @see jaskell.runtime.types.JFunction#init() 47 | */ 48 | public JFunction init() { 49 | return new _3a(); 50 | } 51 | 52 | /* (non-Javadoc) 53 | * @see java.lang.Object#toString() 54 | */ 55 | public String toString() { 56 | return _0 +" : " +_1; 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/test/java/fr/lifl/jaskell/compiler/ConstantPropagatorTest.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.compiler; 2 | 3 | import fr.lifl.jaskell.compiler.core.Application; 4 | import fr.lifl.jaskell.compiler.core.Expression; 5 | import fr.lifl.jaskell.compiler.core.IntegerLiteral; 6 | import fr.lifl.jaskell.compiler.core.Literal; 7 | import fr.lifl.jaskell.compiler.core.QualifiedVariable; 8 | import junit.framework.TestCase; 9 | 10 | /** 11 | * @author bailly 12 | * @version $Id: ConstantPropagatorTest.java 1183 2005-12-07 22:45:19Z nono $ 13 | * */ 14 | public class ConstantPropagatorTest extends TestCase { 15 | 16 | /** 17 | * Constructor for ConstantPropagatorTest. 18 | * @param arg0 19 | */ 20 | public ConstantPropagatorTest(String arg0) { 21 | super(arg0); 22 | } 23 | 24 | public void testSimpleConstant() { 25 | // build expression 26 | Application a = new Application(); 27 | a.addArgument(new IntegerLiteral(1)); 28 | a.addArgument(new IntegerLiteral(1)); 29 | QualifiedVariable qv = new QualifiedVariable("(+)"); 30 | qv.addPathElement("Prelude"); 31 | a.setFunction(qv); 32 | // apply constant propagator 33 | TypeChecker tc= new TypeChecker(); 34 | a.visit(tc); 35 | ConstantPropagator cp = new ConstantPropagator(); 36 | Expression e = (Expression) a.visit(cp); 37 | // compare results 38 | Literal res = new IntegerLiteral(2); 39 | assertEquals(res, e); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/test/java/fr/lifl/jaskell/cli/JaskellTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright Arnaud Bailly, 2003-2013. All Rights Reserved. 3 | * 4 | 5 | * 6 | */ 7 | package fr.lifl.jaskell.cli; 8 | 9 | import java.io.ByteArrayOutputStream; 10 | import java.io.File; 11 | import java.io.FileInputStream; 12 | import java.io.PrintStream; 13 | 14 | import org.junit.Test; 15 | 16 | import static org.fest.assertions.Assertions.assertThat; 17 | 18 | 19 | public class JaskellTest { 20 | 21 | //~ ---------------------------------------------------------------------------------------------------------------- 22 | //~ Methods 23 | //~ ---------------------------------------------------------------------------------------------------------------- 24 | 25 | @Test 26 | public void compilesAndRunOverGivenInputStreamThenSendResultToOutputStream() throws Exception { 27 | File sourceFile = new File(getClass().getResource("/simple.k").getFile()); 28 | ByteArrayOutputStream bytes = new ByteArrayOutputStream(); 29 | Jaskell jaskell = new Jaskell(new FileInputStream(sourceFile),bytes); 30 | 31 | jaskell.run(); 32 | 33 | Exception exception = jaskell.getException(); 34 | if(exception != null) { 35 | exception.printStackTrace(); 36 | } 37 | assertThat(exception).isNull(); 38 | assertThat(new String(bytes.toByteArray())).isEqualTo("24"); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/parser/Equation.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.parser; 2 | 3 | import fr.lifl.jaskell.compiler.core.Expression; 4 | import fr.lifl.jaskell.compiler.core.ExpressionBase; 5 | 6 | import java.util.Iterator; 7 | 8 | /** 9 | * @author bailly 10 | * @version $Id: Equation.java 1154 2005-11-24 21:43:37Z nono $ 11 | */ 12 | public class Equation extends ExpressionBase{ 13 | 14 | private ExpressionList lhs; 15 | private Expression rhs; 16 | 17 | 18 | /** 19 | * Returns the lhs. 20 | * @return Expression 21 | */ 22 | public ExpressionList getLhs() { 23 | return lhs; 24 | } 25 | 26 | /** 27 | * Returns the rhs. 28 | * @return Expression 29 | */ 30 | public Expression getRhs() { 31 | return rhs; 32 | } 33 | 34 | /** 35 | * Sets the lhs. 36 | * @param lhs The lhs to set 37 | */ 38 | public void setLhs(Expression lhs) { 39 | if(lhs instanceof ExpressionList) 40 | this.lhs = (ExpressionList)lhs; 41 | else { 42 | this.lhs = new ExpressionList(); 43 | this.lhs.add(lhs); 44 | } 45 | } 46 | 47 | /** 48 | * Sets the rhs. 49 | * @param rhs The rhs to set 50 | */ 51 | public void setRhs(Expression rhs) { 52 | this.rhs = rhs; 53 | } 54 | 55 | public String toString() { 56 | StringBuffer sb = new StringBuffer(""); 57 | Iterator it = lhs.iterator(); 58 | while(it.hasNext()) 59 | sb.append(it.next()).append(" "); 60 | sb.append(" = ").append(rhs); 61 | return sb.toString(); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/types/FunctionKind.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.compiler.types; 2 | 3 | /** 4 | * 5 | * @author bailly 6 | * @version $Id: FunctionKind.java 1153 2005-11-24 20:47:55Z nono $ 7 | */ 8 | public class FunctionKind implements Kind { 9 | 10 | private Kind from; 11 | private Kind to; 12 | 13 | public static final Kind K_K = new FunctionKind(SimpleKind.K, SimpleKind.K); 14 | /** 15 | * Constructor for FunctionKind. 16 | */ 17 | public FunctionKind(Kind from,Kind to) { 18 | this.from = from; 19 | this.to = to; 20 | } 21 | 22 | /** 23 | * Create a function kind with given number of arguments 24 | * 25 | * @param i an integer 26 | * @return a functionkind 27 | */ 28 | public static Kind makeKind(int i) { 29 | Kind k = K_K; 30 | for(int j= 1;j " + to +")"; 40 | } 41 | 42 | /** 43 | * Method getRange. 44 | * @return Kind 45 | */ 46 | public Kind getRange() { 47 | return to; 48 | } 49 | 50 | 51 | /** 52 | * Method getDomain. 53 | */ 54 | public Kind getDomain() { 55 | return from; 56 | } 57 | 58 | /** 59 | * Method apply. 60 | * @param kind 61 | */ 62 | public Kind apply(Kind kind) { 63 | if(kind.equals(from)) 64 | return to; 65 | throw new TypeError("Cannot apply "+kind +" to "+from); 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/types/CovariantComparator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on Mar 9, 2004 3 | * 4 | * $Log: CovariantComparator.java,v $ 5 | * Revision 1.1 2004/03/10 20:31:56 bailly 6 | * added type comparison classes 7 | * 8 | */ 9 | package fr.lifl.jaskell.compiler.types; 10 | 11 | /** 12 | * A covariant subtype relation implementation 13 | * 14 | * @author bailly 15 | * @version $Id: CovariantComparator.java 1153 2005-11-24 20:47:55Z nono $ 16 | */ 17 | public class CovariantComparator extends TypeComparator { 18 | 19 | /** 20 | * This method assumes both arguments are type applications of 21 | * the same constructor. 22 | * 23 | * @see jaskell.compiler.types.TypeComparator#compare(jaskell.compiler.types.Type, jaskell.compiler.types.Type) 24 | */ 25 | public int compare(Type o1, Type o2) throws UncomparableException { 26 | int ret = 0; 27 | /* iterate over ranges */ 28 | while ((o1 instanceof TypeApplication) 29 | && (o2 instanceof TypeApplication)) { 30 | Type t1 = ((TypeApplication) o1).getRange(); 31 | Type t2 = ((TypeApplication) o2).getRange(); 32 | /* compare */ 33 | int loc = t1.compare(t2); 34 | /* oppposite signs -> mismatch */ 35 | if (((loc < 0) && (ret > 0)) || ((loc > 0) && (ret < 0))) 36 | throw new UncomparableException("Not covariant"); 37 | /* keep current sign */ 38 | if(loc != 0) 39 | ret = loc; 40 | /* loop */ 41 | o1 = ((TypeApplication)o1).getDomain(); 42 | o2 = ((TypeApplication)o2).getDomain(); 43 | } 44 | return ret; 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/types/TypeClassConstraint.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.compiler.types; 2 | 3 | import java.util.Set; 4 | 5 | public class TypeClassConstraint implements TypeConstraint { 6 | private final TypeClass typeClass; 7 | private final Type type; 8 | 9 | public TypeClassConstraint(TypeClass typeClass, Type type) { 10 | this.typeClass = typeClass; 11 | this.type = type; 12 | } 13 | 14 | @Override 15 | public boolean containsVariable(TypeVariable variableType) { 16 | return type.equals(variableType); 17 | } 18 | 19 | @Override 20 | public void collectTo(Set constraints) { 21 | constraints.add(this); 22 | } 23 | 24 | @Override 25 | public TypeConstraint substitute(TypeSubstitution map) { 26 | return new TypeClassConstraint(typeClass,map.substitute(type)); 27 | } 28 | 29 | @Override 30 | public String toString() { 31 | return typeClass + " " + type; 32 | } 33 | 34 | @Override 35 | public boolean equals(Object o) { 36 | if (this == o) return true; 37 | if (o == null || getClass() != o.getClass()) return false; 38 | 39 | TypeClassConstraint that = (TypeClassConstraint) o; 40 | 41 | return typeClass.equals(that.typeClass) && type.equals(that.type); 42 | 43 | } 44 | 45 | @Override 46 | public int hashCode() { 47 | int result = typeClass.hashCode(); 48 | result = 31 * result + type.hashCode(); 49 | return result; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/core/Constructor.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.compiler.core; 2 | 3 | import fr.lifl.jaskell.compiler.JaskellVisitor; 4 | import fr.lifl.jaskell.compiler.types.Type; 5 | 6 | /** 7 | * A class representing data constructors references. 8 | * 9 | * This class is a specialization of Variable for identifying 10 | * constructors occurences. In Haskell, Constructors are normally 11 | * identifiable by naming conventions : either an initiali upper-case letter 12 | * or an initial colon symbol for constructor operators.

13 | * The type of a Constructor occurence is the type of data it constructs. 14 | * 15 | * @author bailly 16 | * @version $Id: Constructor.java 1154 2005-11-24 21:43:37Z nono $ 17 | * */ 18 | public class Constructor extends Variable { 19 | 20 | /** 21 | * Constructor for Constructor. 22 | * @param name 23 | */ 24 | public Constructor(String name) { 25 | super(name); 26 | } 27 | 28 | /** 29 | *Constructs a Constructor with given type 30 | * 31 | * @param name name of constructor 32 | * @param type type of constructed objects 33 | */ 34 | public Constructor(String name, Type type) { 35 | super(name, type); 36 | } 37 | 38 | /** 39 | * @see jaskell.compiler.core.Expression#visit(JaskellVisitor) 40 | */ 41 | public Object visit(JaskellVisitor v) { 42 | return v.visit(this); 43 | } 44 | 45 | /** 46 | * @see java.lang.Object#equals(Object) 47 | */ 48 | public boolean equals(Object obj) { 49 | if (!(obj instanceof Constructor)) 50 | return false; 51 | Constructor v = (Constructor) obj; 52 | return v.getName().equals(getName()); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/core/Pattern.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.compiler.core; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Iterator; 5 | import java.util.List; 6 | 7 | /** 8 | * A tagging interface implemented by all kind of expressions usable 9 | * in a pattern 10 | * 11 | * This interface is implementd by all class of expression usable as 12 | * a pattern in an alternative. 13 | * 14 | * @author bailly 15 | * @version $Id: Pattern.java 1153 2005-11-24 20:47:55Z nono $ 16 | * */ 17 | public abstract class Pattern extends ExpressionBase { 18 | 19 | /** 20 | * This method returns sub-patterns of this pattern as 21 | * an iterator. 22 | * 23 | * @return an Iterator object over all sub-patterns of this 24 | * pattern 25 | * @exception IllegalStateException if this pattern is not valid 26 | */ 27 | public abstract Iterator getSubPatterns(); 28 | 29 | /** 30 | * This method returns the count of bindings for this 31 | * pattern 32 | * 33 | * @return an integer giving the number of variables bind in 34 | * this pattern 35 | */ 36 | public int countBindings() { 37 | int count = 0; 38 | Iterator it = getSubPatterns(); 39 | while (it.hasNext()) 40 | count += ((Pattern) it.next()).countBindings(); 41 | return count; 42 | } 43 | 44 | /** 45 | * This method returns all bindings in this pattern 46 | * 47 | * @return an Iterator over all bindings in this pattern 48 | */ 49 | public List getBindings() { 50 | List l = new ArrayList(); 51 | Iterator it = getSubPatterns(); 52 | while (it.hasNext()) 53 | l.addAll(((Pattern) it.next()).getBindings()); 54 | return l; 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/types/FunctionComparator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on Mar 9, 2004 3 | * 4 | * $Log: FunctionComparator.java,v $ 5 | * Revision 1.1 2004/03/10 20:31:56 bailly 6 | * added type comparison classes 7 | * 8 | */ 9 | package fr.lifl.jaskell.compiler.types; 10 | 11 | /** 12 | * A class that compares function types. 13 | *

14 | * Function types are covariant in their domain and contravariant on their range. 15 | * This class compare method assumes given type objects are constructed from function 16 | * type constructor. 17 | * 18 | * @author bailly 19 | * @version $Id: FunctionComparator.java 1153 2005-11-24 20:47:55Z nono $ 20 | */ 21 | public class FunctionComparator extends TypeComparator { 22 | 23 | /* (non-Javadoc) 24 | * @see jaskell.compiler.types.TypeComparator#compare(jaskell.compiler.types.Type, jaskell.compiler.types.Type) 25 | */ 26 | public int compare(Type o1, Type o2) throws UncomparableException { 27 | int ret = 0; 28 | Type r1 = ((TypeApplication) o1).getRange(); 29 | Type r2 = ((TypeApplication) o2).getRange(); 30 | Type d1 = ((TypeApplication)((TypeApplication) o1).getDomain()).getRange(); 31 | Type d2 = ((TypeApplication)((TypeApplication) o2).getDomain()).getRange(); 32 | /* compare */ 33 | int rcomp = r1.compare(r2); 34 | int dcomp = d1.compare(d2); 35 | /* equality case */ 36 | if((dcomp == 0) && (rcomp == 0)) 37 | return 0; 38 | 39 | if((dcomp <= 0) && (rcomp >=0)) 40 | return -1; 41 | if((dcomp >= 0) && (rcomp <= 0)) 42 | return 1; 43 | /* default case */ 44 | throw new UncomparableException("Type "+o1 + " is not comparable with "+o2); 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/core/FileAndLineTag.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on Jun 9, 2003 3 | * Copyright 2003 Arnaud Bailly 4 | */ 5 | package fr.lifl.jaskell.compiler.core; 6 | 7 | /** 8 | * This tag implementation stores information about the source file 9 | * location of an expression 10 | * 11 | * @author bailly 12 | * @version $Id: FileAndLineTag.java 1153 2005-11-24 20:47:55Z nono $ 13 | */ 14 | public class FileAndLineTag implements Tag { 15 | 16 | private static final String tagname = "source"; 17 | 18 | private String filename; 19 | 20 | private int line; 21 | 22 | private int column; 23 | 24 | /** 25 | * Construct a tag identifying the file name, the line number 26 | * and the column number where the associated expression is 27 | * defined. 28 | * 29 | * @param filename a filename 30 | * @param line an integer denoting line number 31 | * @param col an integer denoting column number 32 | */ 33 | public FileAndLineTag(String filename, int line, int col) { 34 | this.filename = filename; 35 | this.line = line; 36 | this.column = col; 37 | } 38 | 39 | /* (non-Javadoc) 40 | * @see jaskell.compiler.core.Tag#getName() 41 | */ 42 | public String getName() { 43 | return tagname; 44 | } 45 | 46 | /** 47 | * @return 48 | */ 49 | public int getColumn() { 50 | return column; 51 | } 52 | 53 | /** 54 | * @return 55 | */ 56 | public String getFilename() { 57 | return filename; 58 | } 59 | 60 | /** 61 | * @return 62 | */ 63 | public int getLine() { 64 | return line; 65 | } 66 | 67 | 68 | /* (non-Javadoc) 69 | * @see java.lang.Object#toString() 70 | */ 71 | public String toString() { 72 | return filename + "("+line +","+column+")"; 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/core/FloatLiteral.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.compiler.core; 2 | 3 | import fr.lifl.jaskell.compiler.JaskellVisitor; 4 | import fr.lifl.jaskell.compiler.types.Type; 5 | 6 | /** 7 | * @author bailly 8 | * @version $Id: FloatLiteral.java 1154 2005-11-24 21:43:37Z nono $ 9 | * */ 10 | public class FloatLiteral extends Literal { 11 | 12 | /** the float */ 13 | private float fl; 14 | 15 | public FloatLiteral(float fl) { 16 | this.fl = fl; 17 | } 18 | 19 | /** 20 | * Gets float represented by this literal 21 | * 22 | * @return a float value 23 | */ 24 | public float getFloat() { 25 | return fl; 26 | } 27 | 28 | /** 29 | * @see jaskell.compiler.core.Expression#getType() 30 | */ 31 | public Type getType() { 32 | return Primitives.FLOAT; 33 | } 34 | 35 | /** 36 | * @see jaskell.compiler.core.Expression#visit(JaskellVisitor) 37 | */ 38 | public Object visit(JaskellVisitor v) { 39 | return v.visit(this); 40 | } 41 | 42 | /** 43 | * @see jaskell.compiler.core.Literal#unpack() 44 | */ 45 | public Object unpack() { 46 | return new Float(fl); 47 | } 48 | /** 49 | * @see java.lang.Object#equals(Object) 50 | */ 51 | public boolean equals(Object obj) { 52 | if ((obj == null) || !(obj instanceof FloatLiteral)) 53 | return false; 54 | FloatLiteral i = (FloatLiteral) obj; 55 | return i.getFloat() == this.getFloat(); 56 | } 57 | 58 | /** 59 | * @see java.lang.Object#toString() 60 | */ 61 | public String toString() { 62 | return "" + fl; 63 | } 64 | 65 | /* (non-Javadoc) 66 | * @see java.lang.Object#clone() 67 | */ 68 | public Object clone() { 69 | FloatLiteral il = new FloatLiteral(fl); 70 | il.setParent(getParent()); 71 | return il; 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/types/TypeSubstitution.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.compiler.types; 2 | 3 | import com.google.common.collect.ImmutableMap; 4 | import com.google.common.collect.Maps; 5 | 6 | import java.util.Map; 7 | 8 | /** 9 | * @author bailly 10 | */ 11 | public class TypeSubstitution implements TypeVisitor { 12 | 13 | private final Map map; 14 | 15 | public TypeSubstitution() { 16 | this.map = Maps.newHashMap(); 17 | } 18 | 19 | public TypeSubstitution(Map map) { 20 | this.map = map; 21 | } 22 | 23 | /** 24 | * Applies m as a substitution for type variables 25 | * occuring in t 26 | * 27 | * @param t the Type to substitute 28 | * @return a new Type whose all occurrences of mapping in m 29 | * have been replaced 30 | */ 31 | public Type substitute(Type t) { 32 | return t.visit(this); 33 | } 34 | 35 | public Type visit(TypeVariable t) { 36 | Type m = map.get(t); 37 | if (m != null) { 38 | return m.visit(this); 39 | } 40 | return t; 41 | } 42 | 43 | public Type visit(PrimitiveType primitiveType) { 44 | return primitiveType; 45 | } 46 | 47 | public Type visit(TypeApplication typeApplication) { 48 | return Types.apply( 49 | typeApplication.getDomain().visit(this), 50 | typeApplication.getRange().visit(this)); 51 | } 52 | 53 | public Type visit(TypeConstructor typeConstructor) { 54 | return typeConstructor; 55 | } 56 | 57 | @Override 58 | public Type visit(ConstrainedType constrainedType) { 59 | return constrainedType; 60 | } 61 | 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/core/CharLiteral.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.compiler.core; 2 | 3 | import fr.lifl.jaskell.compiler.JaskellVisitor; 4 | import fr.lifl.jaskell.compiler.types.Type; 5 | 6 | /** 7 | * @author bailly 8 | * @version $Id: CharLiteral.java 1154 2005-11-24 21:43:37Z nono $ 9 | * */ 10 | public class CharLiteral extends Literal { 11 | 12 | /** the char */ 13 | private char fl; 14 | 15 | public CharLiteral(char fl) { 16 | this.fl = fl; 17 | } 18 | 19 | /** 20 | * Gets char represented by this literal 21 | * 22 | * @return a char value 23 | */ 24 | public char getChar() { 25 | return fl; 26 | } 27 | 28 | 29 | /** 30 | * @see jaskell.compiler.core.Expression#getType() 31 | */ 32 | public Type getType() { 33 | return Primitives.CHAR; 34 | } 35 | 36 | /** 37 | * @see jaskell.compiler.core.Expression#visit(JaskellVisitor) 38 | */ 39 | public Object visit(JaskellVisitor v) { 40 | return v.visit(this); 41 | } 42 | 43 | /** 44 | * @see jaskell.compiler.core.Literal#unpack() 45 | */ 46 | public Object unpack() { 47 | return new Character(fl); 48 | } 49 | /** 50 | * @see java.lang.Object#equals(Object) 51 | */ 52 | public boolean equals(Object obj) { 53 | if((obj == null) || !(obj instanceof CharLiteral)) 54 | return false; 55 | CharLiteral i = (CharLiteral)obj; 56 | return i.getChar() == this.getChar(); 57 | } 58 | 59 | /** 60 | * @see java.lang.Object#toString() 61 | */ 62 | public String toString() { 63 | return "" + fl; 64 | } 65 | 66 | /* (non-Javadoc) 67 | * @see java.lang.Object#clone() 68 | */ 69 | public Object clone() { 70 | CharLiteral il = new CharLiteral(fl); 71 | il.setParent(getParent()); 72 | return il; 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/core/StringLiteral.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.compiler.core; 2 | 3 | import fr.lifl.jaskell.compiler.JaskellVisitor; 4 | import fr.lifl.jaskell.compiler.types.Type; 5 | 6 | /** 7 | * @author bailly 8 | * @version $Id: StringLiteral.java 1154 2005-11-24 21:43:37Z nono $ 9 | * */ 10 | public class StringLiteral extends Literal { 11 | 12 | /** the String */ 13 | private String string; 14 | 15 | public StringLiteral(String s) { 16 | string = s; 17 | } 18 | 19 | 20 | /** 21 | * @see jaskell.compiler.core.Expression#getType() 22 | */ 23 | public Type getType() { 24 | return Primitives.STRING; 25 | } 26 | 27 | /** 28 | * Returns the string. 29 | * @return String 30 | */ 31 | public String getString() { 32 | return string; 33 | } 34 | 35 | /** 36 | * @see jaskell.compiler.core.Expression#visit(JaskellVisitor) 37 | */ 38 | public Object visit(JaskellVisitor v) { 39 | return v.visit(this); 40 | } 41 | 42 | /** 43 | * @see jaskell.compiler.core.Literal#unpack() 44 | */ 45 | public Object unpack() { 46 | return string; 47 | } 48 | /** 49 | * @see java.lang.Object#equals(Object) 50 | */ 51 | public boolean equals(Object obj) { 52 | if((obj == null) || !(obj instanceof StringLiteral)) 53 | return false; 54 | StringLiteral i = (StringLiteral)obj; 55 | return i.getString().equals(this.getString()); 56 | } 57 | 58 | /** 59 | * @see java.lang.Object#toString() 60 | */ 61 | public String toString() { 62 | return '"' + string + '"'; 63 | } 64 | 65 | 66 | 67 | /* (non-Javadoc) 68 | * @see java.lang.Object#clone() 69 | */ 70 | public Object clone() { 71 | StringLiteral sl = new StringLiteral(string); 72 | sl.setParent(getParent()); 73 | return sl; 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/core/DoubleLiteral.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.compiler.core; 2 | 3 | import fr.lifl.jaskell.compiler.JaskellVisitor; 4 | import fr.lifl.jaskell.compiler.types.Type; 5 | 6 | /** 7 | * @author bailly 8 | * @version $Id: DoubleLiteral.java 1154 2005-11-24 21:43:37Z nono $ 9 | * */ 10 | public class DoubleLiteral extends Literal { 11 | 12 | /** the double */ 13 | private double fl; 14 | 15 | public DoubleLiteral(double fl) { 16 | this.fl = fl; 17 | } 18 | 19 | /** 20 | * Gets double represented by this literal 21 | * 22 | * @return a double value 23 | */ 24 | public double getDouble() { 25 | return fl; 26 | } 27 | 28 | 29 | /** 30 | * @see jaskell.compiler.core.Expression#getType() 31 | */ 32 | public Type getType() { 33 | return Primitives.DOUBLE; 34 | } 35 | 36 | /** 37 | * @see jaskell.compiler.core.Expression#visit(JaskellVisitor) 38 | */ 39 | public Object visit(JaskellVisitor v) { 40 | return v.visit(this); 41 | } 42 | 43 | /** 44 | * @see jaskell.compiler.core.Literal#unpack() 45 | */ 46 | public Object unpack() { 47 | return new Double(fl); 48 | } 49 | /** 50 | * @see java.lang.Object#equals(Object) 51 | */ 52 | public boolean equals(Object obj) { 53 | if((obj == null) || !(obj instanceof DoubleLiteral)) 54 | return false; 55 | DoubleLiteral i = (DoubleLiteral)obj; 56 | return i.getDouble() == this.getDouble(); 57 | } 58 | 59 | /** 60 | * @see java.lang.Object#toString() 61 | */ 62 | public String toString() { 63 | return "" + fl; 64 | } 65 | 66 | /* (non-Javadoc) 67 | * @see java.lang.Object#clone() 68 | */ 69 | public Object clone() { 70 | DoubleLiteral il = new DoubleLiteral(fl); 71 | il.setParent(getParent()); 72 | return il; 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/runtime/types/Event.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on Feb 23, 2004 3 | */ 4 | package fr.lifl.jaskell.runtime.types; 5 | 6 | /** 7 | * @author nono 8 | * @version $Log: Event.java,v $ 9 | * @version Revision 1.1 2004/07/01 15:57:41 bailly 10 | * @version suppression de l'interface Namespace au profit de fr.lifl.parsing.Namespace 11 | * @version modification de la g?n?ration de code pour les constructeurs et les types de donnees 12 | * @version creation d'un type JEvent et d'un constructeur Event 13 | * @version modification du parser pour creer des Event lors de l'analyse syntaxique 14 | * @version 15 | * @version Revision 1.4 2004/06/29 15:25:26 bailly 16 | * @version modification des types pour les messages 17 | * @version 18 | * @version Revision 1.3 2004/04/15 14:26:15 bailly 19 | * @version added toString implementations for all types 20 | * @version 21 | * @version Revision 1.2 2004/03/11 14:53:44 bailly 22 | * @version *** empty log message *** 23 | * @version 24 | * @version Revision 1.1 2004/02/23 16:46:25 bailly 25 | * @version Added generation of MessagePattern from grammar 26 | * @version Fixed constant propagation -> methods are properly 27 | * @version resolved and called if they exist 28 | * @version 29 | */ 30 | public class Event extends JEvent { 31 | 32 | /** 33 | * @param cnx 34 | * @param dir 35 | * @param name 36 | * @param args 37 | */ 38 | public Event(String cnx, JMessage jmsg) { 39 | this._0 = cnx; 40 | this._1 = jmsg; 41 | } 42 | 43 | 44 | public String _0; 45 | 46 | public JMessage _1; 47 | 48 | 49 | /** 50 | * 51 | */ 52 | public Event() { 53 | } 54 | 55 | 56 | /* (non-Javadoc) 57 | * @see java.lang.Object#toString() 58 | */ 59 | public String toString() { 60 | return "{"+_0+'.'+_1+'}'; 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/types/TyvarCollector.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 13 f�vr. 2004 3 | * 4 | * $Log: TyvarCollector.java,v $ 5 | * Revision 1.1 2004/02/13 16:53:40 nono 6 | * 3 fois rien 7 | * 8 | */ 9 | package fr.lifl.jaskell.compiler.types; 10 | 11 | import java.util.HashSet; 12 | import java.util.Set; 13 | 14 | /** 15 | * A class that collects the set of bound variables in a type expression 16 | *

17 | * 18 | * @author bailly 19 | * @version $Id: TyvarCollector.java 1153 2005-11-24 20:47:55Z nono $ 20 | */ 21 | public class TyvarCollector implements TypeVisitor { 22 | 23 | private final Set emptySet = new HashSet(); 24 | 25 | /* (non-Javadoc) 26 | * @see jaskell.compiler.types.TypeVisitor#visit(jaskell.compiler.types.TypeVariable) 27 | */ 28 | public Object visit(TypeVariable t) { 29 | HashSet s = new HashSet(); 30 | s.add(t); 31 | return s; 32 | } 33 | 34 | /* (non-Javadoc) 35 | * @see jaskell.compiler.types.TypeVisitor#visit(jaskell.compiler.types.PrimitiveType) 36 | */ 37 | public Object visit(PrimitiveType primitiveType) { 38 | return new HashSet(); 39 | } 40 | 41 | /* (non-Javadoc) 42 | * @see jaskell.compiler.types.TypeVisitor#visit(jaskell.compiler.types.TypeApplication) 43 | */ 44 | public Object visit(TypeApplication typeApplication) { 45 | Set s1 = (Set)typeApplication.getDomain().visit(this); 46 | Set s2 = (Set)typeApplication.getRange().visit(this); 47 | s1.addAll(s2); 48 | return s1; 49 | } 50 | 51 | /* (non-Javadoc) 52 | * @see jaskell.compiler.types.TypeVisitor#visit(jaskell.compiler.types.TypeConstructor) 53 | */ 54 | public Object visit(TypeConstructor typeConstructor) { 55 | return new HashSet(); 56 | } 57 | 58 | @Override 59 | public Object visit(ConstrainedType constrainedType) { 60 | return new HashSet(); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/core/IntegerLiteral.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.compiler.core; 2 | 3 | import fr.lifl.jaskell.compiler.JaskellVisitor; 4 | import fr.lifl.jaskell.compiler.types.Type; 5 | 6 | /** 7 | * This class encapsulates an int in a IntegerLiteral 8 | * 9 | * @author bailly 10 | * @version $Id: IntegerLiteral.java 1154 2005-11-24 21:43:37Z nono $ 11 | * */ 12 | public class IntegerLiteral extends Literal { 13 | 14 | /** the integer */ 15 | private int integer; 16 | 17 | 18 | public IntegerLiteral(int i) { 19 | this.integer = i; 20 | } 21 | 22 | 23 | /** 24 | * @see jaskell.compiler.core.Expression#getType() 25 | */ 26 | public Type getType() { 27 | return Primitives.INT; 28 | } 29 | 30 | /** 31 | * Returns the integer. 32 | * @return int 33 | */ 34 | public int getInteger() { 35 | return integer; 36 | } 37 | 38 | /** 39 | * @see jaskell.compiler.core.Expression#visit(JaskellVisitor) 40 | */ 41 | public Object visit(JaskellVisitor v) { 42 | return v.visit(this); 43 | } 44 | 45 | /** 46 | * @see jaskell.compiler.core.Literal#unpack() 47 | */ 48 | public Object unpack() { 49 | return new Integer(integer); 50 | } 51 | 52 | /** 53 | * @see java.lang.Object#equals(Object) 54 | */ 55 | public boolean equals(Object obj) { 56 | if((obj == null) || !(obj instanceof IntegerLiteral)) 57 | return false; 58 | IntegerLiteral i = (IntegerLiteral)obj; 59 | return i.getInteger() == this.getInteger(); 60 | } 61 | 62 | /** 63 | * @see java.lang.Object#toString() 64 | */ 65 | public String toString() { 66 | return "" + integer; 67 | } 68 | 69 | /* (non-Javadoc) 70 | * @see java.lang.Object#clone() 71 | */ 72 | public Object clone() { 73 | IntegerLiteral il = new IntegerLiteral(integer); 74 | il.setParent(getParent()); 75 | return il; 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | foldlabs.jaskell 6 | jaskell 7 | jar 8 | 1.0-SNAPSHOT 9 | Jaskell Language library 10 | http://github.com/abailly/jaskell/ 11 | 12 | Jaskell is a subset of Haskell implemented in Java. This library provide a full bytecode compiler for this language. 13 | 14 | 15 | 2003 16 | 17 | 18 | 19 | 20 | Arnaud Bailly 21 | bailly 22 | bailly AT lifl POINT fr 23 | LIFL/Norsys 24 | 25 | Developper 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | junit 34 | junit 35 | 4.10 36 | test 37 | 38 | 39 | 40 | org.easytesting 41 | fest-assert 42 | 1.4 43 | 44 | 45 | 46 | fr.lifl 47 | parsing 48 | 1.4-SNAPSHOT 49 | 50 | 51 | 52 | oqube.patchwork 53 | patchwork-bytes 54 | 4-SNAPSHOT 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/core/Variable.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.compiler.core; 2 | 3 | import fr.lifl.jaskell.compiler.JaskellVisitor; 4 | import fr.lifl.jaskell.compiler.types.Type; 5 | 6 | /** 7 | * A class representing variable references. 8 | * 9 | * This class represents occurences of variable references. The 10 | * name of the variable may be any valid identifier, either qualified or 11 | * unqualified. 12 | * 13 | * @author bailly 14 | * @version $Id: Variable.java 1154 2005-11-24 21:43:37Z nono $ 15 | * */ 16 | public class Variable extends ExpressionBase { 17 | 18 | 19 | /** name of this variable */ 20 | private String name; 21 | 22 | /** 23 | * Constructor for Variable. 24 | * @param name 25 | * @param type 26 | */ 27 | public Variable(String name) { 28 | this.name = name; 29 | } 30 | 31 | /** 32 | *Constructs a variable with given type 33 | * 34 | * @param name name of variable 35 | * @param type type of constructed objects 36 | */ 37 | public Variable(String name, Type type) { 38 | this.name = name; 39 | this.type = type; 40 | } 41 | 42 | 43 | /** 44 | * Returns the name. 45 | * @return String 46 | */ 47 | public String getName() { 48 | return name; 49 | } 50 | 51 | public Object visit(JaskellVisitor v) { 52 | return v.visit(this); 53 | } 54 | 55 | 56 | /** 57 | * @see java.lang.Object#toString() 58 | */ 59 | public String toString() { 60 | return name; 61 | } 62 | 63 | /** 64 | * @see java.lang.Object#equals(Object) 65 | */ 66 | public boolean equals(Object obj) { 67 | if(!(obj instanceof Variable)) 68 | return false; 69 | Variable v = (Variable)obj; 70 | return v.getName().equals(name); 71 | } 72 | 73 | public Object clone() { 74 | Variable var = new Variable(name,getType()); 75 | var.setParent(parent); 76 | return var; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/core/BooleanLiteral.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.compiler.core; 2 | 3 | import fr.lifl.jaskell.compiler.JaskellVisitor; 4 | import fr.lifl.jaskell.compiler.types.Type; 5 | 6 | /** 7 | * @author bailly 8 | * @version $Id: BooleanLiteral.java 1154 2005-11-24 21:43:37Z nono $ 9 | * */ 10 | public class BooleanLiteral extends Literal { 11 | 12 | /** the boolean */ 13 | private boolean fl; 14 | 15 | public BooleanLiteral(boolean fl) { 16 | this.fl = fl; 17 | } 18 | 19 | /** 20 | * Gets boolean represented by this literal 21 | * 22 | * @return a boolean value 23 | */ 24 | public boolean getBoolean() { 25 | return fl; 26 | } 27 | 28 | 29 | /** 30 | * @see jaskell.compiler.core.Expression#getType() 31 | */ 32 | public Type getType() { 33 | return Primitives.BOOL; 34 | } 35 | 36 | /** 37 | * @see jaskell.compiler.core.Expression#visit(JaskellVisitor) 38 | */ 39 | public Object visit(JaskellVisitor v) { 40 | return v.visit(this); 41 | } 42 | 43 | /** 44 | * @see jaskell.compiler.core.Literal#unpack() 45 | */ 46 | public Object unpack() { 47 | return Boolean.valueOf(fl); 48 | } 49 | /** 50 | * @see java.lang.Object#equals(Object) 51 | */ 52 | public boolean equals(Object obj) { 53 | if((obj == null) || !(obj instanceof BooleanLiteral)) 54 | return false; 55 | BooleanLiteral i = (BooleanLiteral)obj; 56 | return i.getBoolean() == this.getBoolean(); 57 | } 58 | 59 | /** 60 | * @see java.lang.Object#toString() 61 | */ 62 | public String toString() { 63 | if(fl) 64 | return "True"; 65 | else 66 | return "False"; 67 | } 68 | 69 | /* (non-Javadoc) 70 | * @see java.lang.Object#clone() 71 | */ 72 | public Object clone() { 73 | BooleanLiteral il = new BooleanLiteral(fl); 74 | il.setParent(getParent()); 75 | return il; 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /src/test/java/fr/lifl/jaskell/parser/NormalizerTest.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.parser; 2 | import fr.lifl.jaskell.compiler.core.Module; 3 | 4 | import java.io.StringReader; 5 | 6 | import junit.framework.TestCase; 7 | 8 | /** 9 | * 10 | * @author bailly 11 | * @version $Id: NormalizerTest.java 1183 2005-12-07 22:45:19Z nono $ 12 | */ 13 | public class NormalizerTest extends TestCase { 14 | 15 | /** 16 | * Constructor for NormalizerTest. 17 | * @param arg0 18 | */ 19 | public NormalizerTest(String arg0) { 20 | super(arg0); 21 | } 22 | 23 | public void testSimple() { 24 | 25 | String text = 26 | "toto True = 0; toto False =1"; 27 | StringReader sr = new StringReader(text); 28 | Yyparser p = new Yyparser(); 29 | p.parse(sr); 30 | Module m = (Module) Module.getToplevels().get("Main"); 31 | System.err.println(m); 32 | } 33 | 34 | public void testLength() { 35 | String text = "length [] = 0 ;" + "length (x : xs) = length xs + 1"; 36 | StringReader sr = new StringReader(text); 37 | Yyparser p = new Yyparser(); 38 | p.parse(sr); 39 | Module m = (Module) Module.getToplevels().get("Main"); 40 | System.err.println(m); 41 | } 42 | 43 | public void testMappairs() { 44 | String text = 45 | " mappairs f [] ys = [] ;" 46 | + " mappairs f (x:xs) [] = [];" 47 | + " mappairs f (x:xs) (y:ys) = f x y : mappairs f xs ys"; 48 | StringReader sr = new StringReader(text); 49 | Yyparser p = new Yyparser(); 50 | p.parse(sr); 51 | Module m = (Module) Module.getToplevels().get("Main"); 52 | System.err.println(m); 53 | } 54 | 55 | public void testMap() { 56 | String text = 57 | " map f [] = [] ;" + " map f (x:xs) = f x : (map f xs)"; 58 | StringReader sr = new StringReader(text); 59 | Yyparser p = new Yyparser(); 60 | p.parse(sr); 61 | Module m = (Module) Module.getToplevels().get("Main"); 62 | System.err.println(m); 63 | } 64 | 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/core/ExpressionTypeContext.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on 11 f�vr. 2004 3 | * 4 | * $Log: ExpressionTypeContext.java,v $ 5 | * Revision 1.3 2004/02/19 14:55:01 nono 6 | * Integrated jaskell to FIDL 7 | * Added rules in grammar to handle messages 8 | * 9 | * Revision 1.2 2004/02/18 17:20:07 nono 10 | * suppressed type classes use and definitions 11 | * 12 | * Revision 1.1 2004/02/11 16:46:51 nono 13 | * Repair ClassMethod missing 14 | * 15 | */ 16 | package fr.lifl.jaskell.compiler.core; 17 | 18 | import fr.lifl.jaskell.compiler.types.Type; 19 | import fr.lifl.jaskell.compiler.types.TypeApplication; 20 | import fr.lifl.jaskell.compiler.types.TypeConstructor; 21 | import fr.lifl.jaskell.compiler.types.TypeContext; 22 | 23 | /** 24 | * @author bailly 25 | * @version $Id: ExpressionTypeContext.java 1154 2005-11-24 21:43:37Z nono $ 26 | */ 27 | public class ExpressionTypeContext implements TypeContext { 28 | 29 | private Expression expr; 30 | 31 | /** 32 | * @param base 33 | */ 34 | public ExpressionTypeContext(Expression base) { 35 | this.expr = base; 36 | } 37 | 38 | 39 | /* (non-Javadoc) 40 | * @see jaskell.compiler.types.TypeContext#resolveType(jaskell.compiler.types.Type) 41 | */ 42 | public Definition resolveType(Type t) { 43 | Expression par = null; 44 | Module mod = null; 45 | /* lookup enclosing namespace */ 46 | for (par = expr.getParent(); 47 | !(par instanceof Module) && (par != null); 48 | par = par.getParent()); 49 | if (par == null) 50 | mod = Module.PRELUDE; /* should lookup all toplevel modules */ 51 | else 52 | mod = (Module) par; 53 | if (t instanceof TypeApplication) 54 | return mod.resolveType( 55 | ((TypeConstructor) t.getConstructor()) 56 | .getName()); 57 | else if (t instanceof TypeConstructor) 58 | return mod.resolveType(((TypeConstructor) t).getName()); 59 | return null; 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/core/Expression.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.compiler.core; 2 | 3 | import fr.lifl.jaskell.compiler.JaskellVisitor; 4 | import fr.lifl.jaskell.compiler.types.Type; 5 | 6 | /** 7 | * @author bailly 8 | * @version $Id: Expression.java 1154 2005-11-24 21:43:37Z nono $ 9 | * */ 10 | public interface Expression{ 11 | 12 | /** 13 | * Returns the tag object associated with the given name 14 | * in this node 15 | * 16 | * @return instance of a Tag or null 17 | */ 18 | public Tag getTag(String name); 19 | 20 | /** 21 | * Store a tag object in this node 22 | * 23 | * @param tag the tag to store. The getName() method 24 | * of Tag interface is used as key 25 | */ 26 | public void putTag(Tag tag); 27 | 28 | /** 29 | * This method retrieves the type of an expression. The returned 30 | * type may be null if type inference has not been done. 31 | * 32 | * @return an object of a subclass of Type or null 33 | */ 34 | public Type getType(); 35 | 36 | /** 37 | * Sets the type of this expression to given type 38 | * 39 | * @param type an object of a subclass of Type or null 40 | */ 41 | public void setType(Type type); 42 | 43 | /** 44 | * Call back for visitor objects 45 | * 46 | * @param v a JaskellVisitor object 47 | */ 48 | public Object visit(JaskellVisitor v); 49 | 50 | /** 51 | * Returns the enclosing context of this expression 52 | * 53 | * @return the enclosing expression of this expression, 54 | * or null if expression is top-level 55 | */ 56 | public Expression getParent(); 57 | 58 | /** 59 | * Defines the enclosing context of this expression 60 | * 61 | * @param parent parent expression for this expression 62 | */ 63 | public void setParent(Expression parent); 64 | /** 65 | * Method resolve. 66 | * @param vname 67 | * @return Binding 68 | */ 69 | Expression lookup(String vname); 70 | 71 | 72 | 73 | } 74 | -------------------------------------------------------------------------------- /src/test/java/fr/lifl/jaskell/compiler/core/ModuleTest.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.compiler.core; 2 | 3 | import junit.framework.TestCase; 4 | 5 | /** 6 | * @author bailly 7 | * @version $Id: ModuleTest.java 1183 2005-12-07 22:45:19Z nono $ 8 | * */ 9 | public class ModuleTest extends TestCase { 10 | 11 | private Module main; 12 | 13 | /** 14 | * Constructor for ModuleTest. 15 | * @param arg0 16 | */ 17 | public ModuleTest(String arg0) { 18 | super(arg0); 19 | } 20 | 21 | 22 | public void testAddTopModule() { 23 | Module mod = new Module("Test", null); 24 | } 25 | 26 | public void testAddTopMainModule() { 27 | Module mod = new Module("Main", null); 28 | } 29 | 30 | public void testAddSubModule() { 31 | Module mod = new Module("Sub", main); 32 | } 33 | 34 | public void testAddDuplicateSubModule() { 35 | try { 36 | Module mod = new Module("Sub", main); 37 | mod = new Module("Sub", main); 38 | } catch (IllegalArgumentException ex) { 39 | assertTrue(true); 40 | return; 41 | } 42 | fail(); 43 | } 44 | 45 | public void testBindOK() { 46 | Module mod = new Module("Sub", main); 47 | mod.bind("toto", new StringLiteral("toto")); 48 | assertEquals("toto",((StringLiteral)mod.lookup("toto")).getString()); 49 | } 50 | 51 | 52 | public void testLookup() { 53 | ExpressionBase obj = new Abstraction(); 54 | Module mod = main; 55 | mod.bind("toto",obj); 56 | Object o1 = mod.lookup("toto"); 57 | assertSame(obj,o1); 58 | } 59 | 60 | public void testDeepLookup() { 61 | Expression obj = new Abstraction(); 62 | Module mod = new Module("Sub",main); 63 | main.bind("toto",obj); 64 | Object o1 = mod.lookupDeep("toto"); 65 | assertNotNull(o1); 66 | assertSame(obj,o1); 67 | } 68 | /** 69 | * @see junit.framework.TestCase#setUp() 70 | */ 71 | protected void setUp() throws Exception { 72 | super.setUp(); 73 | // create new main module 74 | main = new Module("Main",null); 75 | } 76 | 77 | 78 | } 79 | 80 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/core/Literal.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.compiler.core; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Iterator; 5 | import java.util.List; 6 | 7 | /** 8 | * @author bailly 9 | * @version $Id: Literal.java 1153 2005-11-24 20:47:55Z nono $ 10 | * */ 11 | public abstract class Literal extends Pattern { 12 | 13 | /** 14 | * @see jaskell.compiler.core.Pattern#getSubPatterns() 15 | */ 16 | public Iterator getSubPatterns() { 17 | return new EmptyIterator(); 18 | } 19 | 20 | /** 21 | * @see jaskell.compiler.core.Pattern#countBindings() 22 | */ 23 | public int countBindings() { 24 | return 0; 25 | } 26 | 27 | /** 28 | * @see jaskell.compiler.core.Pattern#getBindings() 29 | */ 30 | public List getBindings() { 31 | return new ArrayList(); 32 | } 33 | 34 | 35 | /** 36 | * Return a Java representation of this literal as an object 37 | * 38 | * @return an Object representing this literal in Java 39 | */ 40 | public abstract Object unpack(); 41 | 42 | /** 43 | * Returns a Literal expression representing the given object 44 | * 45 | * @param obj a constant Object which must be a java value compatible 46 | * with one of the literal types 47 | * @return a Literal expression 48 | */ 49 | public static Literal pack(Object obj) { 50 | if (obj instanceof Integer) 51 | return new IntegerLiteral(((Integer) obj).intValue()); 52 | else if (obj instanceof Float) 53 | return new FloatLiteral(((Float) obj).floatValue()); 54 | else if (obj instanceof Double) 55 | return new DoubleLiteral(((Double) obj).doubleValue()); 56 | else if (obj instanceof Boolean) 57 | return new BooleanLiteral(((Boolean) obj).booleanValue()); 58 | else if (obj instanceof Character) 59 | return new CharLiteral(((Character) obj).charValue()); 60 | else if (obj instanceof String) 61 | return new StringLiteral((String) obj); 62 | else 63 | throw new IllegalArgumentException("Unable to pack " + obj); 64 | 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/types/ConstrainedType.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.compiler.types; 2 | 3 | import static java.lang.String.format; 4 | 5 | public class ConstrainedType extends Type { 6 | 7 | private final Type baseType; 8 | private final TypeConstraint typeConstraint; 9 | 10 | public ConstrainedType(Type baseType, TypeConstraint typeConstraint) { 11 | this.baseType = baseType; 12 | this.typeConstraint = typeConstraint; 13 | } 14 | 15 | @Override 16 | public T visit(TypeVisitor v) { 17 | return v.visit(this); 18 | } 19 | 20 | @Override 21 | public boolean contains(TypeVariable variableType) { 22 | return baseType.contains(variableType) || typeConstraint.containsVariable(variableType); 23 | } 24 | 25 | @Override 26 | public void setKind(Kind kind) { 27 | //To change body of implemented methods use File | Settings | File Templates. 28 | } 29 | 30 | public TypeConstraint getTypeConstraint() { 31 | return typeConstraint; 32 | } 33 | 34 | public Type getBaseType() { 35 | return baseType; 36 | } 37 | 38 | @Override 39 | public String toString() { 40 | return format("(%s) => %s", typeConstraint, baseType); 41 | } 42 | 43 | @Override 44 | public boolean equals(Object o) { 45 | if (this == o) return true; 46 | if (o == null || getClass() != o.getClass()) return false; 47 | 48 | ConstrainedType that = (ConstrainedType) o; 49 | 50 | if (baseType != null ? !baseType.equals(that.baseType) : that.baseType != null) return false; 51 | if (typeConstraint != null ? !typeConstraint.equals(that.typeConstraint) : that.typeConstraint != null) 52 | return false; 53 | 54 | return true; 55 | } 56 | 57 | @Override 58 | public int hashCode() { 59 | int result = baseType != null ? baseType.hashCode() : 0; 60 | result = 31 * result + (typeConstraint != null ? typeConstraint.hashCode() : 0); 61 | return result; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/datatypes/PrimitiveConstructor.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.compiler.datatypes; 2 | 3 | import fr.lifl.jaskell.compiler.JaskellVisitor; 4 | import fr.lifl.jaskell.compiler.core.Expression; 5 | import fr.lifl.jaskell.compiler.core.Module; 6 | import fr.lifl.jaskell.compiler.core.Primitives; 7 | import fr.lifl.jaskell.compiler.types.Type; 8 | 9 | /** 10 | * @author nono 11 | * 12 | */ 13 | public class PrimitiveConstructor 14 | extends ConstructorDefinition 15 | implements Primitives { 16 | 17 | private Type dataType; 18 | 19 | /* class name of instances of this constructor */ 20 | private Class klass; 21 | 22 | /** 23 | * Constructor for PrimitiveConstructor. 24 | * @param name 25 | * @param type 26 | */ 27 | public PrimitiveConstructor(String name, DataDefinition ddef, Type[] args,Class klass,Module module) { 28 | super(name, null, module, args); 29 | this.dataType = ddef.getType(); 30 | this.klass = klass; 31 | setParent(ddef); 32 | } 33 | 34 | /** 35 | * Constructor for PrimitiveConstructor with strictness information 36 | * @param name 37 | * @param type 38 | */ 39 | public PrimitiveConstructor(String name, DataDefinition ddef, Type[] args,Class klass,Module module,int[]strictArgs) { 40 | super(name, null, module, args,strictArgs); 41 | this.dataType = ddef.getType(); 42 | this.klass = klass; 43 | setParent(ddef); 44 | } 45 | 46 | 47 | /** 48 | * @see jaskell.compiler.core.Expression#lookup(String) 49 | */ 50 | public Expression lookup(String vname) { 51 | return null; 52 | } 53 | 54 | /** 55 | * @see jaskell.compiler.core.ConstructorDefinition#getDataType() 56 | */ 57 | public Type getDataType() { 58 | return dataType; 59 | } 60 | 61 | /** 62 | * @see java.lang.Object#toString() 63 | */ 64 | public String toString() { 65 | return getName(); 66 | } 67 | 68 | /* (non-Javadoc) 69 | * @see jaskell.compiler.core.Expression#visit(jaskell.compiler.JaskellVisitor) 70 | */ 71 | public Object visit(JaskellVisitor v) { 72 | return v.visit(this); 73 | } 74 | 75 | public Class getJavaClass() { 76 | return klass; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/runtime/types/Closure.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.runtime.types; 2 | 3 | /** 4 | * @author bailly 5 | * @version $Id: Closure.java 1153 2005-11-24 20:47:55Z nono $ 6 | * */ 7 | public abstract class Closure implements JFunction { 8 | 9 | /** Array of JObjects containing collected arguments for this closure */ 10 | protected JObject args[]; 11 | 12 | /** number of arguments */ 13 | protected int nargs; 14 | 15 | /** maximum number of arguments */ 16 | protected int maxargs; 17 | 18 | /** 19 | * Creates a closure with n arguments 20 | * 21 | * @param n number of arguments of Closure. Must be > 0 22 | */ 23 | protected Closure(int n) { 24 | args = new JObject[n]; 25 | nargs = 0; 26 | maxargs = n; 27 | } 28 | 29 | /** 30 | * This method handles boxed - non strict - partial application 31 | * for closure objects. The passed argument is the stored in the 32 | * args array at index nargs. This method assumed the closure is 33 | * not fully applied 34 | * 35 | * @param arg argument to this CLosure 36 | * @return if nargs < args.length, this method returns this closure, 37 | * else it returns the result of evaluating this closure's code 38 | * with given arguments array 39 | */ 40 | public JObject apply(JObject arg) { 41 | if (nargs == maxargs) 42 | throw new IllegalArgumentException( 43 | "Too many arguments to function " + this); 44 | args[nargs++] = arg; 45 | return this; 46 | } 47 | 48 | /** 49 | * Evaluation of Closure object 50 | * 51 | * If number of applied arguments is less than number of 52 | * required arguments, this method yields the closure object itself. 53 | * Otherwise, it calls the abstract eval0() method which 54 | * generally recursively evaluates the applied arguments and 55 | * calls a type specific eval function which 56 | * contains the real code of the method. 57 | * 58 | * @see JObject#eval() 59 | */ 60 | public JObject eval() { 61 | return this; 62 | } 63 | 64 | /* (non-Javadoc) 65 | * @see java.lang.Object#toString() 66 | */ 67 | public String toString() { 68 | return ""; 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/types/TypeConstraintsBuilder.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.compiler.types; 2 | 3 | import com.google.common.collect.Sets; 4 | import org.omg.CORBA.ContextList; 5 | 6 | import java.util.Set; 7 | 8 | public class TypeConstraintsBuilder { 9 | 10 | final Set constraints = Sets.newHashSet(); 11 | 12 | public TypeConstraintsBuilder collectConstraints(Type type) { 13 | type.visit(new Visitors.ConstantTypeVisitor>(constraints) { 14 | 15 | @Override 16 | public Set visit(TypeApplication typeApplication) { 17 | typeApplication.getRange().visit(this); 18 | typeApplication.getDomain().visit(this); 19 | return constraints; 20 | } 21 | 22 | @Override 23 | public Set visit(ConstrainedType constrainedType) { 24 | constraints.add(constrainedType.getTypeConstraint()); 25 | return constraints; 26 | } 27 | }); 28 | 29 | return this; 30 | } 31 | 32 | public boolean isEmpty() { 33 | return constraints.isEmpty(); 34 | } 35 | 36 | public TypeConstraint build() { 37 | if(constraints.size() == 1) { 38 | return constraints.iterator().next(); 39 | } 40 | 41 | return new TypeConstraints(flatten(constraints)); 42 | } 43 | 44 | private Set flatten(Set constraints) { 45 | Set flattened = Sets.newHashSet(); 46 | for (TypeConstraint constraint : constraints) { 47 | constraint.collectTo(flattened); 48 | } 49 | return flattened; 50 | } 51 | 52 | public TypeConstraintsBuilder add(TypeConstraint constraint) { 53 | constraint.collectTo(constraints); 54 | return this; 55 | } 56 | 57 | public TypeConstraintsBuilder add(TypeClassConstraint[] addedConstraints) { 58 | for (TypeClassConstraint constraint : addedConstraints) { 59 | constraint.collectTo(constraints); 60 | } 61 | 62 | return this; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/test/java/fr/lifl/jaskell/compiler/types/TypeComparatorTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on Mar 9, 2004 3 | * 4 | * $Log: TypeComparatorTest.java,v $ 5 | * Revision 1.2 2004/10/17 15:06:16 bailly 6 | * corrected calss to BET API 7 | * removed OverloadDefinition 8 | * 9 | * Revision 1.1 2004/06/24 12:57:44 bailly 10 | * mavenisation + creation arborescence de test 11 | * 12 | * Revision 1.1 2004/03/10 20:31:56 bailly 13 | * added type comparison classes 14 | * 15 | */ 16 | package fr.lifl.jaskell.compiler.types; 17 | import fr.lifl.jaskell.compiler.core.Primitives; 18 | import junit.framework.TestCase; 19 | 20 | /** 21 | * @author bailly 22 | * @version $Id: TypeComparatorTest.java 1183 2005-12-07 22:45:19Z nono $ 23 | */ 24 | public class TypeComparatorTest extends TestCase { 25 | 26 | /** 27 | * Constructor for TypeComparatorTest. 28 | * @param arg0 29 | */ 30 | public TypeComparatorTest(String arg0) { 31 | super(arg0); 32 | } 33 | 34 | /* 35 | * test basic types 36 | */ 37 | public void testVar() throws Exception { 38 | Type t1 = Primitives.INT; 39 | Type t2 = TypeFactory.freshBinding(); 40 | assertEquals(0,t1.compare(t2)); 41 | assertEquals(0,t2.compare(t1)); 42 | } 43 | 44 | public void testVar2() throws Exception { 45 | assertEquals(0,TypeFactory.freshBinding().compare(TypeFactory.freshBinding())); 46 | } 47 | 48 | public void testBase() throws Exception { 49 | try { 50 | Primitives.BOOL.compare(Primitives.INT); 51 | fail(); 52 | }catch(UncomparableException uex) { 53 | 54 | } 55 | } 56 | 57 | public void testList() throws Exception { 58 | Type t1 = Types.apply(Primitives.LIST, Primitives.INT); 59 | Type t2 = Types.apply(Primitives.LIST, TypeFactory.freshBinding()); 60 | assertEquals(0,t1.compare(t2)); 61 | assertEquals(0,t2.compare(t1)); 62 | } 63 | 64 | /* 65 | * (Int -> a) < (a -> b) 66 | */ 67 | public void testFunction() throws Exception { 68 | Type t1 = Types.fun(Primitives.INT, TypeFactory.freshBinding()); 69 | Type t2 = Types.fun(TypeFactory.freshBinding(), TypeFactory.freshBinding()); 70 | assertEquals(0,t1.compare(t2)); 71 | assertEquals(0,t2.compare(t1)); 72 | } 73 | 74 | 75 | 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/types/Visitors.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright Arnaud Bailly, 2003-2013. All Rights Reserved. 3 | * 4 | 5 | * 6 | */ 7 | package fr.lifl.jaskell.compiler.types; 8 | 9 | public class Visitors { 10 | 11 | //~ ---------------------------------------------------------------------------------------------------------------- 12 | //~ Inner Classes 13 | //~ ---------------------------------------------------------------------------------------------------------------- 14 | 15 | public static class IdentityTypeVisitor implements TypeVisitor { 16 | @Override 17 | public Type visit(TypeVariable t) { 18 | return t; 19 | } 20 | 21 | @Override 22 | public Type visit(PrimitiveType primitiveType) { 23 | return primitiveType; 24 | } 25 | 26 | @Override 27 | public Type visit(TypeApplication typeApplication) { 28 | return typeApplication; 29 | } 30 | 31 | @Override 32 | public Type visit(TypeConstructor typeConstructor) { 33 | return typeConstructor; 34 | } 35 | 36 | @Override 37 | public Type visit(ConstrainedType constrainedType) { 38 | return constrainedType; 39 | } 40 | } 41 | 42 | public static class ConstantTypeVisitor implements TypeVisitor { 43 | private final T constant; 44 | 45 | public ConstantTypeVisitor(T constant) { 46 | this.constant = constant; 47 | } 48 | 49 | @Override 50 | public T visit(TypeVariable t) { 51 | return constant; 52 | } 53 | 54 | @Override 55 | public T visit(PrimitiveType primitiveType) { 56 | return constant; 57 | } 58 | 59 | @Override 60 | public T visit(TypeApplication typeApplication) { 61 | return constant; 62 | } 63 | 64 | @Override 65 | public T visit(TypeConstructor typeConstructor) { 66 | return constant; 67 | } 68 | 69 | @Override 70 | public T visit(ConstrainedType constrainedType) { 71 | return constant; 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/test/java/fr/lifl/jaskell/compiler/bytecode/Type2ClassTest.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.compiler.bytecode; 2 | import fr.lifl.jaskell.compiler.core.Module; 3 | import fr.lifl.jaskell.compiler.core.Primitives; 4 | import fr.lifl.jaskell.compiler.types.Type; 5 | import fr.lifl.jaskell.compiler.types.Types; 6 | import junit.framework.TestCase; 7 | 8 | public class Type2ClassTest extends TestCase { 9 | 10 | public Type2ClassTest(String arg) { 11 | super(arg); 12 | } 13 | 14 | public void testType() { 15 | Type t2 = Types.fun(Primitives.INT, Primitives.BOOL); 16 | Type2Class tv = new Type2Class(Module.PRELUDE); 17 | Class cls = (Class) t2.visit(tv); 18 | assertEquals(fr.lifl.jaskell.runtime.types.Closure.class, cls); 19 | } 20 | 21 | public void testTypeGen01() { 22 | Type t2 = 23 | Types.fun( 24 | Primitives.INT, 25 | Types.fun(Primitives.INT, Primitives.BOOL)); 26 | Type2Class tv = new Type2Class(Module.PRELUDE); 27 | Class cls = (Class) t2.visit(tv); 28 | assertEquals( 29 | "fr.lifl.jaskell.runtime.types.Closure", 30 | cls.getName()); 31 | } 32 | 33 | public void testListNameEncoding() { 34 | Type lt = Types.apply(Primitives.LIST, Primitives.INT); 35 | assertEquals("_5bInt_5d", BytecodeGenerator.encodeName2Java(lt.toString())); 36 | } 37 | 38 | public void testListType() { 39 | Type lt = Types.apply(Primitives.LIST, Primitives.INT); 40 | Type2Class tv = new Type2Class(Module.PRELUDE); 41 | Class cls = (Class) lt.visit(tv); 42 | ClassFileWriter writer = new ClassFileWriter("test"); 43 | assertEquals("fr.lifl.jaskell.runtime.types.JList", cls.getName()); 44 | } 45 | 46 | public void testListType2() { 47 | Type lt = 48 | Types.apply( 49 | Primitives.LIST, 50 | Types.apply( 51 | Primitives.LIST, 52 | Types.fun( 53 | Primitives.INT, 54 | Primitives.STRING))); 55 | Type2Class tv = new Type2Class(Module.PRELUDE); 56 | Class cls = (Class) lt.visit(tv); 57 | ClassFileWriter writer = new ClassFileWriter("test"); 58 | BytecodeGenerator.cleanupClassFiles(writer); 59 | } 60 | 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/test/java/fr/lifl/jaskell/parser/ParserTest.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.parser; 2 | import java.io.StringReader; 3 | 4 | import junit.framework.TestCase; 5 | 6 | /** 7 | * 8 | * @author bailly 9 | * @version $Id: ParserTest.java 1183 2005-12-07 22:45:19Z nono $ 10 | */ 11 | public class ParserTest extends TestCase { 12 | 13 | /** 14 | * Constructor for ParserTest. 15 | * @param arg0 16 | */ 17 | public ParserTest(String arg0) { 18 | super(arg0); 19 | } 20 | 21 | /** 22 | * Test simple definition 23 | * length [] = 0 24 | * length x:xs = length xs + 1 25 | */ 26 | public void testLength() { 27 | String text = "module Toto where { length [] = 0 ;" + "length (x : xs) = length xs + 1}"; 28 | StringReader sr = new StringReader(text); 29 | Yyparser p = new Yyparser(); 30 | p.parse(sr); 31 | System.out.println(p.getEquations()); 32 | } 33 | 34 | /** test mappairs definition 35 | * 36 | * mappairs f [] ys = [] 37 | * mappairs f (x:xs) [] = [] 38 | * mappairs f (x:xs) (y:ys) = f x y : mappairs f xs ys 39 | */ 40 | public void testMappairs() { 41 | String text = 42 | "module Main where { length [] = 0 ;" 43 | + "length (x : xs) = length xs + 1;" 44 | + " mappairs f [] ys = [] ;" 45 | + " mappairs f (x:xs) [] = [];" 46 | + " mappairs f (x:xs) (y:ys) = f x y : mappairs f xs ys }"; 47 | StringReader sr = new StringReader(text); 48 | Yyparser p = new Yyparser(); 49 | p.parse(sr); 50 | System.out.println(p.getEquations()); 51 | } 52 | 53 | public void testEmptyClass() { 54 | String text = 55 | "module Main where { class Functor f where { fmap :: (a-> b) -> f a -> f b } }"; 56 | StringReader sr = new StringReader(text); 57 | Yyparser p = new Yyparser(true); 58 | p.parse(sr); 59 | System.out.println(p.getEquations()); 60 | } 61 | 62 | public void testMonadClass() { 63 | String text = 64 | "module Main where { class Monad m where { "+ 65 | " (>>=) :: m a -> (a-> m b) -> m b ;" + 66 | " (>>) :: m a -> m b -> m b; " + 67 | " return :: m -> m a ;" + 68 | // " fail :: String -> m a ;" + 69 | " m >> k = m >>= \\ _ -> k }}"; 70 | StringReader sr = new StringReader(text); 71 | Yyparser p = new Yyparser(true); 72 | p.parse(sr); 73 | System.out.println(p.getEquations()); 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/types/TypeVariable.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.compiler.types; 2 | 3 | 4 | /** 5 | * A class representing type variables in polymorphic types 6 | * 7 | * This class represents polymorphic types. It can be subclassed 8 | * by classes constructed at compile time to represent constrained type 9 | * variables. 10 | * 11 | * @author bailly 12 | * @version $Id: TypeVariable.java 1153 2005-11-24 20:47:55Z nono $ 13 | * */ 14 | public class TypeVariable extends Type { 15 | 16 | 17 | /** name assigned to this type variable */ 18 | private String name; 19 | 20 | /* the kind of this type variable */ 21 | private Kind kind = null; 22 | 23 | /** 24 | * Constructor for TypeVariable. 25 | */ 26 | TypeVariable(String name) { 27 | this.name = name; 28 | } 29 | 30 | public T visit(TypeVisitor v) { 31 | return v.visit(this); 32 | } 33 | 34 | /** 35 | * @see java.lang.Object#toString() 36 | */ 37 | public String toString() { 38 | return name; 39 | } 40 | 41 | /** 42 | * Method getName. 43 | * @return Object 44 | */ 45 | public String getName() { 46 | return name; 47 | } 48 | 49 | public boolean contains(TypeVariable variableType) { 50 | return this.equals(variableType); 51 | } 52 | 53 | public Kind getKind() { 54 | return kind; 55 | } 56 | 57 | /** 58 | * Sets the kind of this type variable 59 | * 60 | * If the given kind is different from null, we check that 61 | * variable as not already be assigned a kind which would be an error. 62 | * 63 | * @param k a Kind 64 | */ 65 | public void setKind(Kind k) { 66 | this.kind = k; 67 | } 68 | 69 | /** 70 | * @see java.lang.Object#equals(Object) 71 | */ 72 | public boolean equals(Object obj) { 73 | if (!(obj instanceof TypeVariable)) 74 | return false; 75 | TypeVariable tv = (TypeVariable) obj; 76 | return tv.name.equals(name); 77 | } 78 | 79 | /* (non-Javadoc) 80 | * @see java.lang.Object#hashCode() 81 | */ 82 | public int hashCode() { 83 | return name.hashCode(); 84 | } 85 | 86 | /* 87 | * Any type variable is a super type of another type 88 | * @see jaskell.compiler.types.Type#compare(jaskell.compiler.types.Type) 89 | */ 90 | public int compare(Type other) throws UncomparableException { 91 | return 0; 92 | } 93 | 94 | } 95 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/types/TypeComparator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on Mar 9, 2004 3 | * 4 | * $Log: TypeComparator.java,v $ 5 | * Revision 1.2 2004/09/07 10:04:04 bailly 6 | * cleared imports 7 | * 8 | * Revision 1.1 2004/03/10 20:31:56 bailly 9 | * added type comparison classes 10 | * 11 | */ 12 | package fr.lifl.jaskell.compiler.types; 13 | 14 | 15 | /** 16 | * Compares two @see{Type} objects. 17 | *

18 | * This class is used to compara two type objects constructed with 19 | * the same type constructor. Each instance is normally associated with a 20 | * TypeConstructor object. The default behavior is covariant : a type t1 is 21 | * a subtype of t2 of all componentns of t1 are subtypes of all component 22 | * of t2. 23 | * 24 | * @author bailly 25 | * @version $Id: TypeComparator.java 1153 2005-11-24 20:47:55Z nono $ 26 | */ 27 | public abstract class TypeComparator { 28 | 29 | /** 30 | * This method compares the two type objects and returns an integer denoting the relation 31 | * between the two objects : 32 | *

    33 | *
  • 0 if the two objects are equals;
  • 34 | *
  • < 0 if o1 is subtype of o2;
  • 35 | *
  • > 0 if o1 is supertype of o2;
  • 36 | *
37 | * If the two objects are uncomparable, this class throws an exception. 38 | * 39 | * @param o1 first type to compare 40 | * @param o2 second type to compare 41 | * @return an integer denoting a subtype relation between the two objects 42 | * @throws UncomparableException if the two objects are uncomparable 43 | */ 44 | public abstract int compare(Type o1, Type o2) throws UncomparableException ; 45 | 46 | /** 47 | * Returns true if the two objects are equal. 48 | * This method is equivalent to the following code fragment : 49 | * 50 | * try { 51 | * return compare(o1,o2) == 0; 52 | * } catch(UncomparableException ex) { 53 | * return false; 54 | * } 55 | * 56 | * 57 | * @param o1 first object to compare 58 | * @param o2 second object to compare 59 | * @return true if the two objects are equal according to this relation 60 | */ 61 | public boolean equals(Type o1, Type o2) { 62 | try { 63 | return compare(o1, o2) == 0; 64 | } catch (UncomparableException ex) { 65 | return false; 66 | } 67 | 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/parser/ExpressionList.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.parser; 2 | 3 | import fr.lifl.jaskell.compiler.JaskellVisitor; 4 | import fr.lifl.jaskell.compiler.core.Expression; 5 | import fr.lifl.jaskell.compiler.core.Tag; 6 | import fr.lifl.jaskell.compiler.types.Type; 7 | 8 | import java.util.ArrayList; 9 | import java.util.Collection; 10 | import java.util.HashMap; 11 | 12 | /** 13 | * @author bailly 14 | * @version $Id: ExpressionList.java 1154 2005-11-24 21:43:37Z nono $ 15 | */ 16 | class ExpressionList extends ArrayList implements Expression { 17 | 18 | /** 19 | * Constructor for ExpressionList. 20 | * @param initialCapacity 21 | */ 22 | public ExpressionList(int initialCapacity) { 23 | super(initialCapacity); 24 | } 25 | 26 | /** 27 | * Constructor for ExpressionList. 28 | */ 29 | public ExpressionList() { 30 | super(); 31 | } 32 | 33 | /** 34 | * Constructor for ExpressionList. 35 | * @param c 36 | */ 37 | public ExpressionList(Collection c) { 38 | super(c); 39 | } 40 | 41 | /** 42 | * @see jaskell.compiler.core.Expression#getType() 43 | */ 44 | public Type getType() { 45 | return null; 46 | } 47 | 48 | /** 49 | * @see jaskell.compiler.core.Expression#setType(Type) 50 | */ 51 | public void setType(Type type) { 52 | } 53 | 54 | /** 55 | * @see jaskell.compiler.core.Expression#visit(JaskellVisitor) 56 | */ 57 | public Object visit(JaskellVisitor v) { 58 | throw new UnsupportedOperationException("Cannot visit an ExpressionList"); 59 | } 60 | 61 | /** 62 | * @see jaskell.compiler.core.Expression#getParent() 63 | */ 64 | public Expression getParent() { 65 | return null; 66 | } 67 | 68 | /** 69 | * @see jaskell.compiler.core.Expression#setParent(Expression) 70 | */ 71 | public void setParent(Expression parent) { 72 | } 73 | 74 | /** 75 | * @see jaskell.compiler.core.Expression#lookup(String) 76 | */ 77 | public Expression lookup(String vname) { 78 | return null; 79 | } 80 | 81 | 82 | protected HashMap tags; 83 | 84 | /* (non-Javadoc) 85 | * @see jaskell.compiler.core.Expression#getTag(java.lang.String) 86 | */ 87 | public Tag getTag(String name) { 88 | if (tags == null) 89 | return null; 90 | else 91 | return (Tag) tags.get(name); 92 | } 93 | 94 | /* (non-Javadoc) 95 | * @see jaskell.compiler.core.Expression#putTag(jaskell.compiler.core.Tag) 96 | */ 97 | public void putTag(Tag tag) { 98 | if (tags == null) 99 | tags = new HashMap(); 100 | tags.put(tag.getName(), tag); 101 | } 102 | 103 | 104 | } 105 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/JaskellVisitor.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright Arnaud Bailly, 2003-2013. All Rights Reserved. 3 | * 4 | 5 | * 6 | */ 7 | package fr.lifl.jaskell.compiler; 8 | 9 | import fr.lifl.jaskell.compiler.core.*; 10 | import fr.lifl.jaskell.compiler.datatypes.ConstructorDefinition; 11 | import fr.lifl.jaskell.compiler.datatypes.DataDefinition; 12 | import fr.lifl.jaskell.compiler.datatypes.PrimitiveConstructor; 13 | import fr.lifl.jaskell.compiler.datatypes.PrimitiveData; 14 | 15 | 16 | /** 17 | * A visitor interface for fucntinal expressions 18 | * 19 | * @author Arnaud.Bailly - bailly@lifl.fr 20 | * @version $Id: JaskellVisitor.java 1154 2005-11-24 21:43:37Z nono $ 21 | */ 22 | public interface JaskellVisitor { 23 | 24 | //~ ---------------------------------------------------------------------------------------------------------------- 25 | //~ Methods 26 | //~ ---------------------------------------------------------------------------------------------------------------- 27 | 28 | Object visit(Abstraction a); 29 | 30 | Object visit(Alternative a); 31 | 32 | Object visit(Application a); 33 | 34 | Object visit(BooleanLiteral a); 35 | 36 | Object visit(CharLiteral a); 37 | 38 | Object visit(Constructor a); 39 | 40 | Object visit(Definition a); 41 | 42 | Object visit(DoubleLiteral a); 43 | 44 | Object visit(FloatLiteral a); 45 | 46 | Object visit(IntegerLiteral a); 47 | 48 | Object visit(Module a); 49 | 50 | Object visit(StringLiteral a); 51 | 52 | Object visit(Variable a); 53 | 54 | Object visit(QualifiedVariable a); 55 | 56 | Object visit(ConstructorPattern a); 57 | 58 | Object visit(LocalBinding a); 59 | 60 | Object visit(PrimitiveFunction f); 61 | 62 | /** 63 | * Method visit. 64 | * 65 | * @param conditional 66 | * 67 | * @return Object 68 | */ 69 | Object visit(Conditional conditional); 70 | 71 | /** 72 | * Method visit. 73 | * 74 | * @param ddef 75 | * 76 | * @return Object 77 | */ 78 | Object visit(DataDefinition ddef); 79 | 80 | /** 81 | * Method visit. 82 | * 83 | * @param cdef 84 | * 85 | * @return Object 86 | */ 87 | Object visit(ConstructorDefinition cdef); 88 | 89 | /** 90 | * Method visit. 91 | * 92 | * @param let 93 | * 94 | * @return Object 95 | */ 96 | Object visit(Let let); 97 | 98 | Object visit(PrimitiveConstructor a); 99 | 100 | Object visit(PrimitiveData a); 101 | 102 | } 103 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/parser/PatternAlternative.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.parser; 2 | 3 | import fr.lifl.jaskell.compiler.JaskellVisitor; 4 | import fr.lifl.jaskell.compiler.core.Expression; 5 | import fr.lifl.jaskell.compiler.core.Pattern; 6 | import fr.lifl.jaskell.compiler.core.Tag; 7 | import fr.lifl.jaskell.compiler.types.Type; 8 | 9 | /** 10 | * @author bailly 11 | * @version $Id: PatternAlternative.java 1154 2005-11-24 21:43:37Z nono $ 12 | */ 13 | public class PatternAlternative implements Expression { 14 | 15 | private Pattern pat ; 16 | private Expression expr; 17 | 18 | /** 19 | * Constructor for PatternAlternative. 20 | */ 21 | public PatternAlternative(Pattern pat, Expression expr) { 22 | this.pat = pat; 23 | this.expr = expr; 24 | } 25 | 26 | /** 27 | * @see jaskell.compiler.core.Expression#getType() 28 | */ 29 | public Type getType() { 30 | return null; 31 | } 32 | 33 | /** 34 | * @see jaskell.compiler.core.Expression#setType(Type) 35 | */ 36 | public void setType(Type type) { 37 | } 38 | 39 | /** 40 | * @see jaskell.compiler.core.Expression#visit(JaskellVisitor) 41 | */ 42 | public Object visit(JaskellVisitor v) { 43 | return null; 44 | } 45 | 46 | /** 47 | * @see jaskell.compiler.core.Expression#getParent() 48 | */ 49 | public Expression getParent() { 50 | return null; 51 | } 52 | 53 | /** 54 | * @see jaskell.compiler.core.Expression#setParent(Expression) 55 | */ 56 | public void setParent(Expression parent) { 57 | } 58 | 59 | /** 60 | * @see jaskell.compiler.core.Expression#lookup(String) 61 | */ 62 | public Expression lookup(String vname) { 63 | return null; 64 | } 65 | 66 | /** 67 | * Returns the expr. 68 | * @return Expression 69 | */ 70 | public Expression getExpr() { 71 | return expr; 72 | } 73 | 74 | /** 75 | * Returns the pat. 76 | * @return Pattern 77 | */ 78 | public Pattern getPattern() { 79 | return pat; 80 | } 81 | 82 | /** 83 | * Sets the expr. 84 | * @param expr The expr to set 85 | */ 86 | public void setExpr(Expression expr) { 87 | this.expr = expr; 88 | } 89 | 90 | /** 91 | * Sets the pat. 92 | * @param pat The pat to set 93 | */ 94 | public void setPattern(Pattern pat) { 95 | this.pat = pat; 96 | } 97 | 98 | /* (non-Javadoc) 99 | * @see jaskell.compiler.core.Expression#getTag(java.lang.String) 100 | */ 101 | public Tag getTag(String name) { 102 | // TODO Auto-generated method stub 103 | return null; 104 | } 105 | 106 | /* (non-Javadoc) 107 | * @see jaskell.compiler.core.Expression#putTag(jaskell.compiler.core.Tag) 108 | */ 109 | public void putTag(Tag tag) { 110 | // TODO Auto-generated method stub 111 | 112 | } 113 | 114 | } 115 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/types/TypeInstantiator.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.compiler.types; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * A visitor implementation for instantiating type variables occurrence 8 | * into a type. 9 | * 10 | * This class works by replacing every occurrence of a variable into a given type 11 | * by a fresh variable or the content of a map. The constraints occurring into the type definition are 12 | * also substituted and checked. 13 | * 14 | * @author bailly 15 | * @version $Id: TypeInstantiator.java 1153 2005-11-24 20:47:55Z nono $ 16 | */ 17 | public class TypeInstantiator implements TypeVisitor { 18 | 19 | /* the base type we work with */ 20 | private Type base; 21 | 22 | /* the substitution we create */ 23 | private Map map = new HashMap(); 24 | 25 | /** 26 | * Constructor TypeInstantiator. 27 | * @param type 28 | * */ 29 | public TypeInstantiator(Type type) { 30 | this.base = type; 31 | } 32 | 33 | public Object visit(PrimitiveType primitiveType) { 34 | return primitiveType; 35 | } 36 | 37 | public Object visit(TypeVariable t) { 38 | Type tv = (Type) map.get(t); 39 | if (tv == null) { 40 | tv = TypeFactory.freshBinding(); 41 | map.put(t, tv); 42 | } 43 | return tv; 44 | } 45 | 46 | /** 47 | * Method instance. 48 | * @return Type 49 | */ 50 | public Type instance() { 51 | Type ret = (Type) base.visit(this); 52 | return ret; 53 | } 54 | 55 | /** 56 | * Returns the base. 57 | * @return Type 58 | */ 59 | public Type getBase() { 60 | return base; 61 | } 62 | 63 | /** 64 | * Returns the mapping created by this instantiator. 65 | * 66 | * The substitution is a map from type variables to type variables. 67 | * 68 | * @return Map 69 | */ 70 | public Map getMap() { 71 | return map; 72 | } 73 | 74 | public void reset() { 75 | map.clear(); 76 | } 77 | 78 | /** 79 | * Sets the base. 80 | * @param base The base to set 81 | */ 82 | public void setBase(Type base) { 83 | this.base = base; 84 | } 85 | 86 | public Object visit(TypeApplication typeApplication) { 87 | Type ta = Types.apply( 88 | (Type) typeApplication.getDomain().visit(this), 89 | (Type) typeApplication.getRange().visit(this)); 90 | return ta; 91 | } 92 | 93 | public Object visit(TypeConstructor typeConstructor) { 94 | return typeConstructor; 95 | } 96 | 97 | @Override 98 | public Object visit(ConstrainedType constrainedType) { 99 | return constrainedType; 100 | } 101 | 102 | /** 103 | * Sets the map. 104 | * @param map The map to set 105 | */ 106 | public void setMap(Map map) { 107 | this.map = map; 108 | } 109 | 110 | 111 | } 112 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/core/Definition.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.compiler.core; 2 | 3 | import fr.lifl.jaskell.compiler.JaskellVisitor; 4 | import fr.lifl.jaskell.compiler.types.Type; 5 | 6 | /** 7 | * A class for named definitions of objects in a module 8 | * 9 | * This class stores all data pertaining to a definition in a module : 10 | * the name of the definition, its type, and the expression it references. 11 | * 12 | * @author bailly 13 | * @version $Id: Definition.java 1154 2005-11-24 21:43:37Z nono $ 14 | * */ 15 | public class Definition extends ExpressionBase implements Binding { 16 | 17 | /** name of variable */ 18 | private String name; 19 | 20 | /** definition of this object */ 21 | private Expression definition; 22 | 23 | /* module where this definition is located */ 24 | private Module module; 25 | 26 | /** 27 | * Constructor for Definition. 28 | */ 29 | public Definition(String name, Type type, Expression expr, Module module) { 30 | this.name = module.getName() + "." + name; 31 | this.definition = expr; 32 | this.module = module; 33 | setType(type); 34 | setParent(module); 35 | } 36 | 37 | public Definition() { 38 | } 39 | 40 | /** 41 | * Returns the definition. 42 | * @return Expression 43 | */ 44 | public Expression getDefinition() { 45 | return definition; 46 | } 47 | 48 | /** 49 | * Returns the module. 50 | * @return Module 51 | */ 52 | public Module getModule() { 53 | return module; 54 | } 55 | 56 | /** 57 | * Returns the name. 58 | * @return String 59 | */ 60 | public String getName() { 61 | return name; 62 | } 63 | 64 | /** 65 | * Sets the definition. 66 | * @param definition The definition to set 67 | */ 68 | public void setDefinition(Expression definition) { 69 | this.definition = definition; 70 | } 71 | 72 | /** 73 | * Sets the module. 74 | * @param module The module to set 75 | */ 76 | public void setModule(Module module) { 77 | this.module = module; 78 | } 79 | 80 | /** 81 | * Sets the name. 82 | * @param name The name to set 83 | */ 84 | public void setName(String name) { 85 | this.name = name; 86 | } 87 | 88 | 89 | public Object visit(JaskellVisitor v) { 90 | return v.visit(this); 91 | } 92 | /** 93 | * @see jaskell.compiler.core.Binding#isStrict() 94 | */ 95 | public boolean isStrict() { 96 | return false; 97 | } 98 | 99 | /** 100 | * @see jaskell.compiler.core.Expression#lookup(String) 101 | */ 102 | public Expression lookup(String vname) { 103 | return parent.lookup(vname); 104 | } 105 | 106 | /* (non-Javadoc) 107 | * @see java.lang.Object#toString() 108 | */ 109 | public String toString() { 110 | return name +"::"+getType(); 111 | } 112 | 113 | } 114 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/core/QualifiedVariable.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.compiler.core; 2 | 3 | import fr.lifl.jaskell.compiler.JaskellVisitor; 4 | import fr.lifl.jaskell.compiler.types.Type; 5 | 6 | import java.util.ArrayList; 7 | import java.util.Iterator; 8 | import java.util.List; 9 | 10 | /** 11 | * A class representing qualified variable occurences. 12 | * 13 | * This class represents occurences of variable references with qualified 14 | * path prepended. The only difference lays in the resolution method which starts 15 | * from the first component of qualified name. 16 | * 17 | * @author bailly 18 | * @version $Id: QualifiedVariable.java 1154 2005-11-24 21:43:37Z nono $ 19 | * */ 20 | public class QualifiedVariable extends Variable { 21 | 22 | /** list of path components */ 23 | private List path = new ArrayList(); 24 | 25 | /** 26 | * Constructor for Variable. 27 | * @param name 28 | * @param type 29 | */ 30 | public QualifiedVariable(String name) { 31 | super(name); 32 | } 33 | 34 | /** 35 | *Constructs a variable with given type 36 | * 37 | * @param name name of variable 38 | * @param type type of constructed objects 39 | */ 40 | public QualifiedVariable(String name, Type type) { 41 | super(name, type); 42 | } 43 | 44 | /** 45 | * Returns the path. 46 | * @return Path 47 | */ 48 | public List getPath() { 49 | return path; 50 | } 51 | 52 | /** 53 | * Adds a component to the path 54 | * @param path The path to set 55 | */ 56 | public void addPathElement(String elem) { 57 | this.path.add(elem); 58 | } 59 | 60 | /** 61 | * @see jaskell.compiler.core.Expression#lookup(String) 62 | */ 63 | public Expression lookup(String vname) { 64 | Module mod = null; 65 | Iterator it = getPath().iterator(); 66 | while (it.hasNext()) { 67 | String mname = (String) it.next(); 68 | if (mod != null) 69 | mod = (Module) mod.lookup(mname); 70 | else 71 | mod = (Module) Module.getToplevels().get(mname); 72 | } 73 | // module found - locate and generate instructions 74 | if (mod != null) 75 | return mod.lookup(vname); 76 | return null; 77 | } 78 | 79 | /** 80 | * @see jaskell.compiler.core.Expression#visit(JaskellVisitor) 81 | */ 82 | public Object visit(JaskellVisitor v) { 83 | return v.visit(this); 84 | } 85 | 86 | public String toString() { 87 | StringBuffer sb = new StringBuffer(""); 88 | Iterator it = path.iterator(); 89 | while (it.hasNext()) 90 | sb.append(it.next()).append('.'); 91 | return sb.append(getName()).toString(); 92 | } 93 | 94 | public Object clone() { 95 | QualifiedVariable qv = new QualifiedVariable(getName(),getType()); 96 | Iterator it =path.iterator(); 97 | while(it.hasNext()) qv.addPathElement((String)it.next()); 98 | qv.setParent(getParent()); 99 | return qv; 100 | } 101 | } -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/types/TypeConstraints.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.compiler.types; 2 | 3 | import com.google.common.base.Function; 4 | 5 | import javax.annotation.Nullable; 6 | import java.util.Collections; 7 | import java.util.Map; 8 | import java.util.Set; 9 | 10 | import static com.google.common.collect.Iterables.transform; 11 | import static com.google.common.collect.Sets.newHashSet; 12 | 13 | public class TypeConstraints implements TypeConstraint { 14 | 15 | private final Set constraints; 16 | 17 | public TypeConstraints(TypeConstraint constraint, TypeConstraint... constraints) { 18 | this.constraints = newHashSet(); 19 | this.constraints.add(constraint); 20 | Collections.addAll(this.constraints, constraints); 21 | } 22 | 23 | public TypeConstraints(Set constraints) { 24 | this.constraints = newHashSet(constraints); 25 | } 26 | 27 | @Override 28 | public boolean containsVariable(TypeVariable variableType) { 29 | boolean containsVariable = false; 30 | for (TypeConstraint constraint : constraints) { 31 | containsVariable |= constraint.containsVariable(variableType); 32 | } 33 | return containsVariable; 34 | } 35 | 36 | @Override 37 | public void collectTo(Set constraints) { 38 | for (TypeConstraint constraint : this.constraints) { 39 | constraint.collectTo(constraints); 40 | } 41 | } 42 | 43 | @Override 44 | public TypeConstraint substitute(TypeSubstitution map) { 45 | return new TypeConstraints(newHashSet(transform(constraints, substituteTypes(map)))); 46 | } 47 | 48 | private Function substituteTypes(final TypeSubstitution map) { 49 | return new Function() { 50 | @Override 51 | public TypeConstraint apply(@Nullable TypeConstraint input) { 52 | return input.substitute(map); 53 | } 54 | }; 55 | } 56 | 57 | @Override 58 | public boolean equals(Object o) { 59 | if (this == o) return true; 60 | if (o == null || getClass() != o.getClass()) return false; 61 | 62 | TypeConstraints that = (TypeConstraints) o; 63 | 64 | return !(constraints != null ? !constraints.equals(that.constraints) : that.constraints != null); 65 | 66 | } 67 | 68 | @Override 69 | public int hashCode() { 70 | return constraints != null ? constraints.hashCode() : 0; 71 | } 72 | 73 | @Override 74 | public String toString() { 75 | StringBuilder sb = new StringBuilder(); 76 | for (TypeConstraint constraint : constraints) { 77 | sb.append(constraint.toString()).append(", "); 78 | } 79 | sb.delete(sb.length() - 2, sb.length()); 80 | return sb.toString(); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/types/TypeConstructor.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.compiler.types; 2 | 3 | 4 | /** 5 | * A class representing type constructors, both builtin and user defined. 6 | *

7 | * This class represents type constructors which are used to construct types. 8 | * A type constructor is itself a type. Instances of this class include builtin 9 | * type constructors like (->) for function types, [] for list types, () for 10 | * unit type, (,),(,,),(,,,)... for tuple types.

11 | * It also includes user defined type constructors or simple primitive types 12 | * like Int or Char. 13 | * 14 | * @author bailly 15 | * @version $Id: TypeConstructor.java 1153 2005-11-24 20:47:55Z nono $ 16 | */ 17 | public class TypeConstructor extends Type { 18 | 19 | /* name of this constructor */ 20 | private String name; 21 | 22 | /* kind of this constructor */ 23 | private Kind kind; 24 | 25 | /** 26 | * Constructor for TypeConstructor. 27 | * 28 | * @param name the name of this type constructor. Usually starts 29 | * with upper case for user defined data 30 | */ 31 | TypeConstructor(String name) { 32 | this(name, null); 33 | } 34 | 35 | TypeConstructor(String name, Kind kind) { 36 | this.name = name; 37 | this.kind = kind; 38 | } 39 | 40 | public boolean contains(TypeVariable variableType) { 41 | return false; 42 | } 43 | 44 | public Kind getKind() { 45 | return kind; 46 | } 47 | 48 | /** 49 | * Sets the kind of this type variable 50 | * 51 | * @param k a Kind 52 | */ 53 | public void setKind(Kind k) { 54 | this.kind = k; 55 | } 56 | 57 | /** 58 | * @see java.lang.Object#toString() 59 | */ 60 | public String toString() { 61 | return name; 62 | } 63 | 64 | /** 65 | * @see java.lang.Object#equals(Object) 66 | */ 67 | public boolean equals(Object obj) { 68 | if (obj == null || !(obj instanceof TypeConstructor)) 69 | return false; 70 | TypeConstructor at = (TypeConstructor) obj; 71 | return at.name.equals(name); 72 | } 73 | 74 | public T visit(TypeVisitor v) { 75 | return v.visit(this); 76 | } 77 | 78 | /** 79 | * Returns the name. 80 | * @return String 81 | */ 82 | public String getName() { 83 | return name; 84 | } 85 | 86 | /** 87 | * Sets the name. 88 | * @param name The name to set 89 | */ 90 | public void setName(String name) { 91 | this.name = name; 92 | } 93 | 94 | /* (non-Javadoc) 95 | * @see jaskell.compiler.types.Type#compare(jaskell.compiler.types.Type) 96 | */ 97 | public int compare(Type other) throws UncomparableException { 98 | if(this.equals(other)) 99 | return 0; 100 | else if(!(other instanceof TypeConstructor)) 101 | return -other.compare(this); 102 | else 103 | throw new UncomparableException("Type constructors are uncomparable : "+this+" <> "+other); 104 | } 105 | 106 | } 107 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/core/Conditional.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.compiler.core; 2 | 3 | import fr.lifl.jaskell.compiler.JaskellVisitor; 4 | 5 | /** 6 | * A class representing simple if-then-else conditions 7 | * 8 | * This class represents simple conditional constructs whihc may be used 9 | * instead of the more general and complicated Alternative construct. 10 | * 11 | * @author bailly 12 | * @version $Id: Conditional.java 1154 2005-11-24 21:43:37Z nono $ 13 | */ 14 | public class Conditional extends ExpressionBase { 15 | 16 | /** 17 | * conditional expression 18 | */ 19 | private Expression condition; 20 | 21 | /** 22 | * true branch 23 | */ 24 | private Expression ifTrue; 25 | 26 | /** 27 | * false branch 28 | */ 29 | private Expression ifFalse; 30 | 31 | 32 | /** 33 | * @see jaskell.compiler.core.Expression#visit(JaskellVisitor) 34 | */ 35 | public Object visit(JaskellVisitor v) { 36 | return v.visit(this); 37 | } 38 | 39 | 40 | /** 41 | * Returns the condition. 42 | * @return Expression 43 | */ 44 | public Expression getCondition() { 45 | return condition; 46 | } 47 | 48 | /** 49 | * Returns the ifFalse. 50 | * @return Expression 51 | */ 52 | public Expression getIfFalse() { 53 | return ifFalse; 54 | } 55 | 56 | /** 57 | * Returns the ifTrue. 58 | * @return Expression 59 | */ 60 | public Expression getIfTrue() { 61 | return ifTrue; 62 | } 63 | 64 | /** 65 | * Sets the condition. 66 | * @param condition The condition to set 67 | */ 68 | public void setCondition(Expression condition) { 69 | this.condition = condition; 70 | condition.setParent(this); 71 | } 72 | 73 | /** 74 | * Sets the ifFalse. 75 | * @param ifFalse The ifFalse to set 76 | */ 77 | public void setIfFalse(Expression ifFalse) { 78 | this.ifFalse = ifFalse; 79 | ifFalse.setParent(this); 80 | } 81 | 82 | /** 83 | * Sets the ifTrue. 84 | * @param ifTrue The ifTrue to set 85 | */ 86 | public void setIfTrue(Expression ifTrue) { 87 | this.ifTrue = ifTrue; 88 | ifTrue.setParent(this); 89 | } 90 | 91 | 92 | /* (non-Javadoc) 93 | * @see java.lang.Object#toString() 94 | */ 95 | public String toString() { 96 | StringBuffer sb = new StringBuffer("if "); 97 | sb.append(condition); 98 | sb.append(" then ").append(ifTrue); 99 | sb.append(" else ").append(ifFalse); 100 | return sb.toString(); 101 | 102 | } 103 | 104 | public Object clone() throws CloneNotSupportedException{ 105 | Conditional cond = new Conditional(); 106 | cond.setCondition((Expression)((ExpressionBase)condition).clone()); 107 | cond.setIfFalse((Expression)((ExpressionBase)ifFalse).clone()); 108 | cond.setIfTrue((Expression)((ExpressionBase)ifTrue).clone()); 109 | cond.setType(getType()); 110 | cond.setParent(getParent()); 111 | return cond; 112 | } 113 | 114 | } 115 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/core/QualifiedConstructor.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.compiler.core; 2 | 3 | import fr.lifl.jaskell.compiler.JaskellVisitor; 4 | import fr.lifl.jaskell.compiler.types.Type; 5 | 6 | import java.util.ArrayList; 7 | import java.util.Iterator; 8 | import java.util.List; 9 | 10 | /** 11 | * A class representing qualified variable occurences. 12 | * 13 | * This class represents occurences of variable references with qualified 14 | * path prepended. The only difference lays in the resolution method which starts 15 | * from the first component of qualified name. 16 | * 17 | * @author bailly 18 | * @version $Id: QualifiedConstructor.java 1154 2005-11-24 21:43:37Z nono $ 19 | * */ 20 | public class QualifiedConstructor extends Constructor { 21 | 22 | /** list of path components */ 23 | private List path = new ArrayList(); 24 | 25 | /** 26 | * Constructor for Variable. 27 | * @param name 28 | * @param type 29 | */ 30 | public QualifiedConstructor(String name) { 31 | super(name); 32 | } 33 | 34 | /** 35 | *Constructs a variable with given type 36 | * 37 | * @param name name of variable 38 | * @param type type of constructed objects 39 | */ 40 | public QualifiedConstructor(String name, Type type) { 41 | super(name, type); 42 | } 43 | 44 | /** 45 | * Returns the path. 46 | * @return Path 47 | */ 48 | public List getPath() { 49 | return path; 50 | } 51 | 52 | /** 53 | * Adds a component to the path 54 | * @param path The path to set 55 | */ 56 | public void addPathElement(String elem) { 57 | this.path.add(elem); 58 | } 59 | 60 | /** 61 | * @see jaskell.compiler.core.Expression#lookup(String) 62 | */ 63 | public Expression lookup(String vname) { 64 | Module mod = null; 65 | Iterator it = getPath().iterator(); 66 | while (it.hasNext()) { 67 | String mname = (String) it.next(); 68 | if (mod != null) 69 | mod = (Module) mod.lookup(mname); 70 | else 71 | mod = (Module) parent.lookup(mname); 72 | } 73 | // module found - locate and generate instructions 74 | if (mod != null) 75 | return mod.lookup(vname); 76 | return null; 77 | } 78 | 79 | /** 80 | * @see jaskell.compiler.core.Expression#visit(JaskellVisitor) 81 | */ 82 | public Object visit(JaskellVisitor v) { 83 | return v.visit(this); 84 | } 85 | 86 | public String toString() { 87 | StringBuffer sb = new StringBuffer(""); 88 | Iterator it = path.iterator(); 89 | while (it.hasNext()) 90 | sb.append(it.next()).append('.'); 91 | return sb.append(getName()).toString(); 92 | } 93 | 94 | public Object clone() { 95 | QualifiedConstructor qv = 96 | new QualifiedConstructor(getName(), getType()); 97 | Iterator it = path.iterator(); 98 | while (it.hasNext()) 99 | qv.addPathElement((String) it.next()); 100 | qv.setParent(getParent()); 101 | return qv; 102 | } 103 | 104 | } 105 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/core/ExpressionBase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on Jun 8, 2003 3 | * Copyright 2003 Arnaud Bailly 4 | */ 5 | package fr.lifl.jaskell.compiler.core; 6 | 7 | import fr.lifl.jaskell.compiler.JaskellVisitor; 8 | import fr.lifl.jaskell.compiler.types.Type; 9 | 10 | import java.util.HashMap; 11 | 12 | /** 13 | * @author bailly 14 | * @version $Id: ExpressionBase.java 1154 2005-11-24 21:43:37Z nono $ 15 | */ 16 | public abstract class ExpressionBase implements Expression, Cloneable { 17 | 18 | /** stores type */ 19 | protected Type type; 20 | 21 | /** stores parent expression */ 22 | protected Expression parent; 23 | 24 | /** 25 | * @see jaskell.compiler.core.Expression#getType() 26 | */ 27 | public Type getType() { 28 | TypeTag tag = (TypeTag) getTag("type"); 29 | if (tag != null) 30 | return tag.getType(); 31 | else 32 | return null; 33 | } 34 | 35 | /** 36 | * @see jaskell.compiler.core.Expression#setType(Type) 37 | */ 38 | public void setType(Type type) { 39 | if (type != null) 40 | type.setContext(new ExpressionTypeContext(this)); 41 | putTag(new TypeTag(type)); 42 | } 43 | 44 | /** 45 | * @see jaskell.compiler.core.Expression#getParent() 46 | */ 47 | public Expression getParent() { 48 | return parent; 49 | } 50 | 51 | /** 52 | * @see jaskell.compiler.core.Expression#setParent(Expression) 53 | */ 54 | public void setParent(Expression parent) { 55 | this.parent = parent; 56 | } 57 | 58 | /** 59 | * @see jaskell.compiler.core.Expression#lookup(String) 60 | */ 61 | public Expression lookup(String vname) { 62 | if (parent != null) 63 | return parent.lookup(vname); 64 | return null; 65 | } 66 | 67 | /** 68 | * type expressions are used only at parsing stage. They should not 69 | * be visited 70 | * 71 | * @see jaskell.compiler.core.Expression#visit(JaskellVisitor) 72 | */ 73 | public Object visit(JaskellVisitor v) { 74 | throw new UnsupportedOperationException( 75 | "No visit method is defined for class " + getClass()); 76 | } 77 | 78 | /* (non-Javadoc) 79 | * @see java.lang.Object#clone() 80 | */ 81 | public Object clone() throws CloneNotSupportedException { 82 | return super.clone(); 83 | } 84 | 85 | protected HashMap tags; 86 | 87 | /* (non-Javadoc) 88 | * @see jaskell.compiler.core.Expression#getTag(java.lang.String) 89 | */ 90 | public Tag getTag(String name) { 91 | if (tags == null) 92 | return null; 93 | else 94 | return (Tag) tags.get(name); 95 | } 96 | 97 | /* (non-Javadoc) 98 | * @see jaskell.compiler.core.Expression#putTag(jaskell.compiler.core.Tag) 99 | */ 100 | public void putTag(Tag tag) { 101 | if (tags == null) 102 | tags = new HashMap(); 103 | tags.put(tag.getName(), tag); 104 | } 105 | 106 | } 107 | -------------------------------------------------------------------------------- /src/test/java/fr/lifl/jaskell/compiler/LambdaLifterTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on May 27, 2003 by Arnaud Bailly - bailly@lifl.fr 3 | * Copyright 2003 - Arnaud Bailly 4 | */ 5 | package fr.lifl.jaskell.compiler; 6 | import fr.lifl.jaskell.compiler.core.Module; 7 | import fr.lifl.jaskell.parser.Yyparser; 8 | 9 | import java.io.StringReader; 10 | 11 | import junit.framework.TestCase; 12 | 13 | /** 14 | * @author bailly 15 | * @version $Id: LambdaLifterTest.java 1183 2005-12-07 22:45:19Z nono $ 16 | */ 17 | public class LambdaLifterTest extends TestCase { 18 | 19 | /** 20 | * Constructor for LambdaLifterTest. 21 | * @param arg0 22 | */ 23 | public LambdaLifterTest(String arg0) { 24 | super(arg0); 25 | } 26 | 27 | @Override 28 | public void setUp() throws Exception { 29 | Module.getToplevels().clear(); 30 | } 31 | 32 | public void testSimple() { 33 | String text = "module Main where {f x = (\\ y -> x + y) 4 + 2}"; 34 | StringReader sr = new StringReader(text); 35 | Yyparser p = new Yyparser(false); 36 | p.parse(sr); 37 | Module m = (Module) Module.getToplevels().get("Main"); 38 | /* typecheck module */ 39 | LambdaLifter ll = new LambdaLifter(m); 40 | m.visit(ll); 41 | /* retrieve lambda0 */ 42 | assertNotNull(m.lookup("lambda0")); 43 | System.out.println(m); 44 | } 45 | 46 | public void testNested() { 47 | String text = "module Main where {f x = (\\ y -> x + (\\ z -> y * x + z)) 4 + 2}"; 48 | StringReader sr = new StringReader(text); 49 | Yyparser p = new Yyparser(false); 50 | p.parse(sr); 51 | Module m = (Module) Module.getToplevels().get("Main"); 52 | /* typecheck module */ 53 | LambdaLifter ll = new LambdaLifter(m); 54 | m.visit(ll); 55 | /* retrieve lambda0 */ 56 | assertNotNull(m.lookup("lambda0")); 57 | assertNotNull(m.lookup("lambda1")); 58 | System.out.println(m); 59 | } 60 | 61 | public void testLet() { 62 | String text = "module Main where {f x y = let a k = x + k in (a 1) * y}"; 63 | StringReader sr = new StringReader(text); 64 | Yyparser p = new Yyparser(false); 65 | p.parse(sr); 66 | Module m = (Module) Module.getToplevels().get("Main"); 67 | System.out.println(m); 68 | /* typecheck module */ 69 | LambdaLifter ll = new LambdaLifter(m); 70 | m.visit(ll); 71 | /* retrieve lambda0 */ 72 | assertNotNull(m.lookup("lambda0")); 73 | System.out.println(m); 74 | } 75 | 76 | public void testRecursiveLet() { 77 | String text = "module Main where {f x = let { even 0 = true; even x = odd (x + -1); odd 0 =false; odd x = even (x + -1) } in odd x; main = f 10}"; 78 | StringReader sr = new StringReader(text); 79 | Yyparser p = new Yyparser(false); 80 | p.parse(sr); 81 | Module m = (Module) Module.getToplevels().get("Main"); 82 | System.out.println(m); 83 | /* typecheck module */ 84 | LambdaLifter ll = new LambdaLifter(m); 85 | m.visit(ll); 86 | /* retrieve lambda0 */ 87 | assertNotNull(m.lookup("lambda0")); 88 | System.out.println(m); 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/bytecode/Type2String.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright Arnaud Bailly, 2003-2013. All Rights Reserved. 3 | * 4 | 5 | * 6 | */ 7 | package fr.lifl.jaskell.compiler.bytecode; 8 | 9 | import fr.lifl.jaskell.compiler.types.*; 10 | 11 | import oqube.bytes.TypeHelper; 12 | 13 | 14 | /** 15 | * @author bailly 16 | * @version $Id: Type2String.java 1154 2005-11-24 21:43:37Z nono $ 17 | */ 18 | public class Type2String implements TypeVisitor { 19 | 20 | //~ ---------------------------------------------------------------------------------------------------------------- 21 | //~ Constructors 22 | //~ ---------------------------------------------------------------------------------------------------------------- 23 | 24 | /* store the set of constraints against which variables may be resolved */ 25 | // private Set context; 26 | 27 | /** 28 | * Constructor for Type2String. 29 | */ 30 | public Type2String( /*Set context*/) { 31 | // this.context = context; 32 | } 33 | 34 | //~ ---------------------------------------------------------------------------------------------------------------- 35 | //~ Methods 36 | //~ ---------------------------------------------------------------------------------------------------------------- 37 | 38 | public Object visit(TypeVariable t) { 39 | // /* try to find constraint for variable t */ 40 | // Iterator it = context.iterator(); 41 | // /* a list to store matching constraints */ 42 | // List clss = new ArrayList(); 43 | // while (it.hasNext()) { 44 | // TypeConstraint tc = (TypeConstraint) it.next(); 45 | // TypeClass cls = tc.typeClass; 46 | // Type ta = tc.typeExpression; 47 | // if (t.equals(ta) 48 | // || (ta instanceof TypeApplication 49 | // && ((TypeApplication) ta).getConstructor().equals(t))) 50 | // clss.add(cls); 51 | // } 52 | // if (!clss.isEmpty()) 53 | // /* TODO - try to find a suitable constraint */ 54 | // return "L"+BytecodeGenerator.encodeName2Java(((TypeClass) clss.get(0)).getName())+";"; 55 | // else 56 | return "Ljaskell/runtime/types/JObject;"; 57 | } 58 | 59 | public Object visit(PrimitiveType primitiveType) { 60 | return TypeHelper.getInternalName(primitiveType.getJavaClass()); 61 | } 62 | 63 | public Object visit(TypeApplication typeApplication) { 64 | return typeApplication.getConstructor().visit(this); 65 | } 66 | 67 | public Object visit(TypeConstructor typeConstructor) { 68 | return "L" + BytecodeGenerator.encodeName2Java(typeConstructor.getName()) + ";"; 69 | } 70 | 71 | @Override 72 | public Object visit(ConstrainedType constrainedType) { 73 | return "Ljaskell/runtime/types/JObject;"; 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/runtime/types/JError.java: -------------------------------------------------------------------------------- 1 | /*______________________________________________________________________________ 2 | * 3 | * Copyright 2003 Arnaud Bailly - NORSYS 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 9 | * (1) Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * (2) Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in 14 | * the documentation and/or other materials provided with the 15 | * distribution. 16 | * 17 | * (3) The name of the author may not be used to endorse or promote 18 | * products derived from this software without specific prior 19 | * written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 25 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 31 | * OF THE POSSIBILITY OF SUCH DAMAGE. 32 | * -------------------------------------------------------------------- 33 | * Created on Jun 22, 2003 34 | * $Log: JError.java,v $ 35 | * Revision 1.1 2003/06/23 06:33:31 bailly 36 | * Debugging 37 | * Added JError primitive type to raise runtime exceptions 38 | * when no match is found 39 | * 40 | */ 41 | package fr.lifl.jaskell.runtime.types; 42 | 43 | /** 44 | * A class that is used to generate runtime errors in Jaskell. 45 | * 46 | * This subclass of {@link java.lang.Error} represents a runtime error 47 | * occuring in a Jaskell programm such that unmatched argument in a 48 | * case or unresolved links. 49 | * 50 | * @author bailly 51 | * @version $Id: JError.java 1153 2005-11-24 20:47:55Z nono $ 52 | */ 53 | public class JError extends RuntimeException implements JObject { 54 | 55 | /** 56 | * 57 | */ 58 | public JError() { 59 | super(); 60 | } 61 | 62 | /** 63 | * @param message 64 | */ 65 | public JError(String message) { 66 | super(message); 67 | } 68 | 69 | /** 70 | * @param message 71 | * @param cause 72 | */ 73 | public JError(String message, Throwable cause) { 74 | super(message, cause); 75 | } 76 | 77 | /** 78 | * @param cause 79 | */ 80 | public JError(Throwable cause) { 81 | super(cause); 82 | } 83 | 84 | /* (non-Javadoc) 85 | * @see jaskell.runtime.types.JObject#eval() 86 | */ 87 | public JObject eval() { 88 | return this; 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/core/PrimitiveFunction.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.compiler.core; 2 | 3 | import fr.lifl.jaskell.compiler.JaskellVisitor; 4 | import fr.lifl.jaskell.compiler.bytecode.PrimitivesCodeGenerator; 5 | import fr.lifl.jaskell.compiler.types.PrimitiveType; 6 | import fr.lifl.jaskell.compiler.types.Type; 7 | 8 | /** 9 | * @author Arnaud Bailly 10 | * @version $Id: PrimitiveFunction.java 1154 2005-11-24 21:43:37Z nono $ 11 | * 12 | */ 13 | public class PrimitiveFunction extends Abstraction implements Primitives { 14 | 15 | /** name of this primitive function */ 16 | private String name; 17 | 18 | /** number of arguments */ 19 | private int args; 20 | 21 | /** class implementing this function */ 22 | private Class klass; 23 | 24 | /** 25 | * Constructs a PrimitiveFunction with given name, module and type 26 | */ 27 | public PrimitiveFunction(String name, Module module, Type type,Class cls) { 28 | setParent(module); 29 | this.name = name; 30 | setType(type); 31 | this.args = PrimitiveType.getArgsCount(type); 32 | this.klass = cls; 33 | /* register function with bytecode generator if cls not null */ 34 | if(cls !=null) 35 | PrimitivesCodeGenerator.registerStaticPrimitive(this); 36 | /* bind definition in module */ 37 | module.bind(name,this); 38 | } 39 | 40 | /** 41 | * @see jaskell.compiler.core.Binding#getName() 42 | */ 43 | public String getName() { 44 | return name; 45 | } 46 | 47 | /** 48 | * @see jaskell.compiler.core.Binding#isStrict() 49 | */ 50 | public boolean isStrict() { 51 | return true; 52 | } 53 | 54 | /** 55 | * @see jaskell.compiler.core.Abstraction#getBody() 56 | */ 57 | public Expression getBody() { 58 | return null; 59 | } 60 | 61 | /** 62 | * @see jaskell.compiler.core.Abstraction#setBody(Expression) 63 | */ 64 | public void setBody(Expression body) { 65 | } 66 | 67 | /** 68 | * @see jaskell.compiler.core.Expression#visit(JaskellVisitor) 69 | */ 70 | public Object visit(JaskellVisitor v) { 71 | return v.visit(this); 72 | } 73 | 74 | /** 75 | * @see jaskell.compiler.core.Abstraction#getCount() 76 | */ 77 | public int getCount() { 78 | return args; 79 | } 80 | 81 | /** 82 | * All arguments are strict in a primitive function 83 | * 84 | * @see jaskell.compiler.core.Abstraction#isStrict(int) 85 | */ 86 | public boolean isStrict(int i) { 87 | if(i < args) 88 | return true; 89 | else 90 | return false; 91 | } 92 | 93 | /** 94 | * @see jaskell.compiler.core.Binding#getDefinition() 95 | */ 96 | public Expression getDefinition() { 97 | return this; 98 | } 99 | 100 | /* (non-Javadoc) 101 | * @see java.lang.Object#toString() 102 | */ 103 | public String toString() { 104 | return "native: "+name; 105 | } 106 | 107 | /** 108 | * @return 109 | */ 110 | public Class getKlass() { 111 | return klass; 112 | } 113 | 114 | /** 115 | * @param class1 116 | */ 117 | public void setKlass(Class class1) { 118 | klass = class1; 119 | } 120 | 121 | /* (non-Javadoc) 122 | * @see java.lang.Object#clone() 123 | */ 124 | public Object clone() throws CloneNotSupportedException { 125 | throw new CloneNotSupportedException(); 126 | } 127 | 128 | } -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/cli/Jaskell.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.cli; 2 | 3 | import fr.lifl.jaskell.compiler.ConstantPropagator; 4 | import fr.lifl.jaskell.compiler.LambdaLifter; 5 | import fr.lifl.jaskell.compiler.StrictnessAnalyzer; 6 | import fr.lifl.jaskell.compiler.TypeChecker; 7 | import fr.lifl.jaskell.compiler.bytecode.BytecodeGenerator; 8 | import fr.lifl.jaskell.compiler.bytecode.CodeGenerator; 9 | import fr.lifl.jaskell.compiler.bytecode.Type2Class; 10 | import fr.lifl.jaskell.compiler.core.Module; 11 | import fr.lifl.jaskell.parser.Yyparser; 12 | import oqube.bytes.loading.ClassFileLoader; 13 | 14 | import java.io.InputStream; 15 | import java.io.OutputStream; 16 | import java.io.PrintStream; 17 | import java.lang.reflect.InvocationTargetException; 18 | import java.lang.reflect.Method; 19 | 20 | 21 | public class Jaskell implements Runnable { 22 | 23 | private final Yyparser parser = new Yyparser(); 24 | private final StrictnessAnalyzer strictnessAnalyzer = new StrictnessAnalyzer(); 25 | private final TypeChecker typeChecker = new TypeChecker(); 26 | private final ConstantPropagator constantPropagator = new ConstantPropagator(); 27 | private final CodeGenerator codeGenerator = new CodeGenerator(); 28 | private final ClassFileLoader classFileLoader = new ClassFileLoader(ClassLoader.getSystemClassLoader()); 29 | 30 | private final InputStream inputStream; 31 | private final OutputStream outputStream; 32 | 33 | 34 | private Exception exception; 35 | 36 | public Jaskell(InputStream inputStream, OutputStream outputStream) { 37 | this.inputStream = inputStream; 38 | this.outputStream = outputStream; 39 | } 40 | 41 | @Override 42 | public void run() { 43 | BytecodeGenerator.setLoader(classFileLoader); 44 | parser.parse(inputStream); 45 | 46 | for (Module m : parser.getModules()) { 47 | /* generate types */ 48 | Type2Class t2c = new Type2Class(m); 49 | //m.visit(t2c); 50 | /* generate code */ 51 | LambdaLifter ll = new LambdaLifter(m); 52 | StrictnessAnalyzer sa = new StrictnessAnalyzer(); 53 | TypeChecker tc = new TypeChecker(); 54 | CodeGenerator cg = new CodeGenerator(); 55 | /* work ! */ 56 | m.visit(ll); 57 | m.visit(sa); 58 | m.visit(tc); 59 | /* generate types */ 60 | m.visit(t2c); 61 | /* generate code */ 62 | m.visit(cg); 63 | /* write */ 64 | CodeGenerator.cleanupClassFiles(classFileLoader); 65 | } 66 | 67 | Object theMain = null; 68 | PrintStream oldOut = System.out; 69 | try { 70 | System.setOut(new PrintStream(outputStream)); 71 | runMain(); 72 | } catch (Exception e) { 73 | this.exception = e; 74 | } finally { 75 | System.setOut(oldOut); 76 | } 77 | } 78 | 79 | private Object runMain() throws NoSuchMethodException, ClassNotFoundException, InvocationTargetException, IllegalAccessException { 80 | Class cls = classFileLoader.loadClass("Main$Module"); 81 | Method met = cls.getMethod("main", new Class[]{String[].class}); 82 | return met.invoke(null, new Object[]{new String[0]}); 83 | } 84 | 85 | public Exception getException() { 86 | return exception; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/types/TypeContext.java: -------------------------------------------------------------------------------- 1 | /*______________________________________________________________________________ 2 | * 3 | * Copyright 2003 Arnaud Bailly - NORSYS/LIFL 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 9 | * (1) Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * (2) Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in 14 | * the documentation and/or other materials provided with the 15 | * distribution. 16 | * 17 | * (3) The name of the author may not be used to endorse or promote 18 | * products derived from this software without specific prior 19 | * written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 25 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 31 | * OF THE POSSIBILITY OF SUCH DAMAGE. 32 | *______________________________________________________________________________ 33 | * 34 | * Created on Oct 20, 2003 35 | * $Log: TypeContext.java,v $ 36 | * Revision 1.3 2004/02/18 17:20:07 nono 37 | * suppressed type classes use and definitions 38 | * 39 | * Revision 1.2 2004/02/09 20:40:02 nono 40 | * mise a jour repository central 41 | * 42 | * Revision 1.1 2003/10/20 19:10:28 bailly 43 | * Refactore type constraints handling : added a ConstrainedType 44 | * Type subclass, changed code to handle adding of TypeConstraints, 45 | * made constraints as linked lists within a ConstrainedType, 46 | * changed unification and substitution 47 | * 48 | * Added a TypeFactory class as an interface to type expressions 49 | * creation. 50 | * 51 | */ 52 | package fr.lifl.jaskell.compiler.types; 53 | 54 | import fr.lifl.jaskell.compiler.core.Definition; 55 | 56 | /** 57 | * An interface to allow communication between type expressions 58 | * and the context in which they are used. 59 | *

60 | * This interface is used mainly within type package fr.lifl.to 61 | * allow retrieval of context dependent information, most 62 | * notably type-classes instances declarations. 63 | * 64 | * @author nono 65 | * @version $Id: TypeContext.java 1154 2005-11-24 21:43:37Z nono $ 66 | */ 67 | public interface TypeContext { 68 | 69 | /** 70 | * This method tries to locate a Definition for the 71 | * given Type object according to this context. 72 | * A Definition object or a null reference is returned. 73 | * 74 | * @param t a Type to find Definition for 75 | * @return Definition object or null if not found in context 76 | */ 77 | public Definition resolveType(Type t); 78 | } 79 | -------------------------------------------------------------------------------- /src/test/java/fr/lifl/jaskell/compiler/types/ConstrainedTypeTest.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.compiler.types; 2 | 3 | import org.junit.Ignore; 4 | import org.junit.Test; 5 | 6 | import static fr.lifl.jaskell.compiler.types.TypeTest.FUNCTION; 7 | import static fr.lifl.jaskell.compiler.types.Types.*; 8 | import static org.fest.assertions.Assertions.assertThat; 9 | import static org.junit.Assert.assertEquals; 10 | 11 | /** 12 | * TODO handle constraints identification 13 | * TODO handle superclass/subclass constraint widening 14 | * TODO handle constraints unification on variables 15 | * TODO handle constraints removal with instance 16 | * TODO multivariate typeclasses constraints 17 | * TODO type identification constraints (eg. a ~ b) 18 | */ 19 | public class ConstrainedTypeTest { 20 | 21 | private static Type eqA = constraint(var("a"), typeClass("Eq", var("a"))); 22 | private static Type eqB = constraint(var("b"), typeClass("Eq", var("b"))); 23 | private static Type eqC = constraint(var("c"), typeClass("Eq", var("c"))); 24 | 25 | @Test 26 | public void typeClassConstraintIsPropagatedWhenApplyingType() { 27 | Type functionWithConstrainedDomain = apply(apply(FUNCTION, 28 | eqA), 29 | var("b")); 30 | 31 | Type functionWithConstrainedRange = apply(apply(FUNCTION, 32 | var("b")), 33 | eqA); 34 | 35 | Type constrainedFunctionType = constraint( 36 | apply(apply(FUNCTION, var("a")), var("b")), typeClass("Eq", var("a")) 37 | ); 38 | 39 | assertThat(functionWithConstrainedDomain).isEqualTo(constrainedFunctionType); 40 | assertThat(functionWithConstrainedRange).isEqualTo(constraint( 41 | apply(apply(FUNCTION, var("b")), var("a")), typeClass("Eq", var("a")) 42 | )); 43 | } 44 | 45 | 46 | @Test 47 | public void multipleConstraintsAreComposedWhenApplyingType() throws Exception { 48 | assertThat(apply(apply(FUNCTION, eqA), eqB)).isEqualTo(constraint( 49 | apply(apply(FUNCTION, var("a")), var("b")), 50 | typeClass("Eq", var("a")), 51 | typeClass("Eq", var("b")))); 52 | 53 | assertThat(apply(apply(FUNCTION, eqC),apply(apply(FUNCTION, eqA), eqB))).isEqualTo(constraint( 54 | apply(apply(FUNCTION, var("c")), apply(apply(FUNCTION, var("a")), var("b"))), 55 | typeClass("Eq", var("c")), 56 | typeClass("Eq", var("a")), 57 | typeClass("Eq", var("b")))); 58 | } 59 | 60 | @Test 61 | public void redundantConstraintsAreIgnored() throws Exception { 62 | assertThat(apply(apply(FUNCTION, eqA), eqA)).isEqualTo(constraint( 63 | apply(apply(FUNCTION, var("a")), var("a")), 64 | typeClass("Eq", var("a")))); 65 | } 66 | 67 | @Ignore("constraints with typeclasses do not work (yet)") 68 | @Test 69 | public void testConstraint2() { 70 | TypeVariable v1 = new TypeVariable("m"); 71 | Type v2 = new TypeVariable("a"); 72 | Type v3 = new TypeVariable("b"); 73 | Type t = new TypeApplication(new TypeApplication(FUNCTION, v2), new TypeApplication(v1, v3)); 74 | t = new TypeApplication(new TypeApplication(FUNCTION, new TypeApplication(v1, v2)), t); 75 | t = new TypeApplication(new TypeApplication(FUNCTION, t), new TypeApplication(v1, v3)); 76 | assertEquals("(Monad m) => (((m a) -> (a -> (m b))) -> (m b))", t.makeString()); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/test/java/fr/lifl/jaskell/compiler/types/TypeUnifierTest.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.compiler.types; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | import static com.google.common.collect.Maps.newHashMap; 9 | import static fr.lifl.jaskell.compiler.core.Primitives.BOOL; 10 | import static fr.lifl.jaskell.compiler.types.Types.*; 11 | import static org.fest.assertions.Assertions.assertThat; 12 | 13 | public class TypeUnifierTest { 14 | 15 | TypeUnifier unifier = new TypeUnifier(); 16 | final Type a = var("a"); 17 | final Type b = var("b"); 18 | final Type c = var("c"); 19 | final Type f = fun(b, c); 20 | 21 | @Test 22 | public void unifiesAVariableAndPrimitiveTypeYieldsAPrimitiveType() throws Exception { 23 | 24 | HashMap map = newHashMap(); 25 | assertThat(unifier.unify(a, BOOL, map)).isEqualTo(BOOL); 26 | assertThat(map.get(a)).isEqualTo(BOOL); 27 | 28 | assertThat(unifier.unify(BOOL, a, newHashMap())).isEqualTo(BOOL); 29 | } 30 | 31 | @Test 32 | public void unifiesAVariableAndAVariableYieldsAVariable() throws Exception { 33 | 34 | HashMap map = newHashMap(); 35 | assertThat(unifier.unify(a, b, map)).isEqualTo(b); 36 | assertThat(map.get(a)).isEqualTo(b); 37 | 38 | assertThat(unifier.unify(b, a, newHashMap())).isEqualTo(a); 39 | } 40 | 41 | @Test 42 | public void unifiesAVariableAndAFunctionTypeYieldsFunctionType() throws Exception { 43 | HashMap map = newHashMap(); 44 | assertThat(unifier.unify(a, f, map)).isEqualTo(f); 45 | assertThat(map.get(a)).isEqualTo(f); 46 | 47 | assertThat(unifier.unify(f, a, map)).isEqualTo(f); 48 | assertThat(map.get(a)).isEqualTo(f); 49 | } 50 | 51 | @Test 52 | public void unifiesTwoFunctionsMapsVariablesToPrimitives() throws Exception { 53 | Map map = newHashMap(); 54 | assertThat(unifier.unify(fun(a, b), fun(BOOL, BOOL), map)).isEqualTo(fun(BOOL, BOOL)); 55 | assertThat(map.get(a)).isEqualTo(BOOL); 56 | assertThat(map.get(b)).isEqualTo(BOOL); 57 | } 58 | 59 | @Test(expected = TypeError.class) 60 | public void cannotUnifyAVariableAndAFunctionWithSameVariable() throws Exception { 61 | unifier.unify(a, fun(a, b), newHashMap()); 62 | } 63 | 64 | @Test 65 | public void unifiesConstrainedVariableToVariableYieldsConstrainedVariable() throws Exception { 66 | Map map = newHashMap(); 67 | Type eqB = constraint(b, typeClass("Eq", b)); 68 | Type eqA = constraint(a, typeClass("Eq", a)); 69 | 70 | assertThat(unifier.unify(a, eqB, map)).isEqualTo(eqB); 71 | assertThat(map.get(a)).isEqualTo(eqB); 72 | 73 | map = newHashMap(); 74 | assertThat(unifier.unify(eqB, a, map)).isEqualTo(eqA); 75 | assertThat(map.get(b)).isEqualTo(a); 76 | } 77 | 78 | @Test 79 | public void propagatesRangeSubstitutionToDomainWhenUnifyingTypeApplication() throws Exception { 80 | assertThat(unifier.unify(fun(a, a), fun(b, BOOL),newHashMap())).isEqualTo(fun(BOOL, BOOL)); 81 | } 82 | 83 | @Test 84 | public void unifiesConstrainedTypeWithPrimitiveTypes() throws Exception { 85 | Type t = var("t"); 86 | Type eqTA = constraint(fun(apply(t, a), a), typeClass("Eq", apply(t, a))); 87 | Type f = fun(b, BOOL); 88 | 89 | assertThat(unifier.unify(eqTA,f,newHashMap())).isEqualTo(constraint(fun(apply(t, BOOL), BOOL), typeClass("Eq", apply(t, BOOL)))); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/core/Application.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright Arnaud Bailly, 2003-2013. All Rights Reserved. 3 | * 4 | 5 | * 6 | */ 7 | package fr.lifl.jaskell.compiler.core; 8 | 9 | import java.util.ArrayList; 10 | import java.util.Iterator; 11 | import java.util.List; 12 | 13 | import fr.lifl.jaskell.compiler.JaskellVisitor; 14 | 15 | 16 | /** 17 | * This class represents applicative forms. An application is basically just a sequence of expressions which can later 18 | * be evaluated through a function. 19 | * 20 | * @author bailly 21 | * @version $Id: Application.java 1154 2005-11-24 21:43:37Z nono $ 22 | */ 23 | public class Application extends ExpressionBase { 24 | 25 | //~ ---------------------------------------------------------------------------------------------------------------- 26 | //~ Instance fields 27 | //~ ---------------------------------------------------------------------------------------------------------------- 28 | 29 | /** list of expressions in the application */ 30 | private List args = new ArrayList(); 31 | 32 | /** functional expression for this application */ 33 | private Expression function; 34 | 35 | //~ ---------------------------------------------------------------------------------------------------------------- 36 | //~ Methods 37 | //~ ---------------------------------------------------------------------------------------------------------------- 38 | 39 | /** 40 | * Adds an argument to this application 41 | * 42 | * @param expr Expression object to add 43 | */ 44 | public void addArgument(Expression expr) { 45 | args.add(expr); 46 | expr.setParent(this); 47 | } 48 | 49 | public void setArgument(Expression expr, int pos) { 50 | args.set(pos, expr); 51 | expr.setParent(this); 52 | } 53 | 54 | public Expression getArgument(int pos) { 55 | return (Expression) args.get(pos); 56 | } 57 | 58 | /** 59 | * @see jaskell.compiler.core.Expression#visit(JaskellVisitor) 60 | */ 61 | public Object visit(JaskellVisitor v) { 62 | return v.visit(this); 63 | } 64 | 65 | /** 66 | * Returns the args. 67 | * 68 | * @return List 69 | */ 70 | public List getArgs() { 71 | return args; 72 | } 73 | 74 | /** 75 | * Returns the function. 76 | * 77 | * @return Expression 78 | */ 79 | public Expression getFunction() { 80 | return function; 81 | } 82 | 83 | /** 84 | * Sets the function. 85 | * 86 | * @param function The function to set 87 | */ 88 | public void setFunction(Expression function) { 89 | this.function = function; 90 | function.setParent(this); 91 | } 92 | 93 | public String toString() { 94 | StringBuffer sb = new StringBuffer("("); 95 | sb.append(function); 96 | Iterator it = args.iterator(); 97 | while (it.hasNext()) 98 | sb.append(' ').append(it.next()); 99 | sb.append(')'); 100 | return sb.toString(); 101 | } 102 | 103 | public Object clone() throws CloneNotSupportedException { 104 | Application app = new Application(); 105 | Iterator it = args.iterator(); 106 | while (it.hasNext()) 107 | app.addArgument((Expression) ((ExpressionBase) it.next()).clone()); 108 | 109 | app.setFunction((Expression) ((ExpressionBase) function).clone()); 110 | app.setType(getType()); 111 | return app; 112 | } 113 | 114 | } 115 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/types/TypeFactory.java: -------------------------------------------------------------------------------- 1 | /*______________________________________________________________________________ 2 | * 3 | * Copyright 2003 Arnaud Bailly - NORSYS/LIFL 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 9 | * (1) Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * (2) Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in 14 | * the documentation and/or other materials provided with the 15 | * distribution. 16 | * 17 | * (3) The name of the author may not be used to endorse or promote 18 | * products derived from this software without specific prior 19 | * written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 25 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 31 | * OF THE POSSIBILITY OF SUCH DAMAGE. 32 | *______________________________________________________________________________ 33 | * 34 | * Created on Oct 20, 2003 35 | * $Log: TypeFactory.java,v $ 36 | * Revision 1.4 2004/02/19 14:55:01 nono 37 | * Integrated jaskell to FIDL 38 | * Added rules in grammar to handle messages 39 | * 40 | * Revision 1.3 2004/02/18 17:20:07 nono 41 | * suppressed type classes use and definitions 42 | * 43 | * Revision 1.2 2004/02/09 20:40:02 nono 44 | * mise a jour repository central 45 | * 46 | * Revision 1.1 2003/10/20 19:10:28 bailly 47 | * Refactore type constraints handling : added a ConstrainedType 48 | * Type subclass, changed code to handle adding of TypeConstraints, 49 | * made constraints as linked lists within a ConstrainedType, 50 | * changed unification and substitution 51 | * 52 | * Added a TypeFactory class as an interface to type expressions 53 | * creation. 54 | * 55 | */ 56 | package fr.lifl.jaskell.compiler.types; 57 | 58 | import java.util.Iterator; 59 | import java.util.List; 60 | import java.util.WeakHashMap; 61 | 62 | /** 63 | * A focal point for constructing type expressions. 64 | * 65 | * This factory class exports various static methods to 66 | * construct different type expressions : type variables, 67 | * cosntrained types, type applications, ... 68 | * 69 | * @author nono 70 | * @version $Id: TypeFactory.java 1153 2005-11-24 20:47:55Z nono $ 71 | */ 72 | public class TypeFactory { 73 | 74 | private static final String freshPrefix = "t"; 75 | 76 | private static int freshIndex = 0; 77 | 78 | /* map of all bindings already defined - to create fresh variables */ 79 | private static WeakHashMap bounds = new WeakHashMap(); 80 | 81 | 82 | /** 83 | * Method freshBinding. 84 | * @return LocalBinding 85 | */ 86 | public static Type freshBinding() { 87 | String fresh = freshPrefix + freshIndex; 88 | while (bounds.get(fresh) != null) 89 | fresh = freshPrefix + ++freshIndex; 90 | return makeTypeVariable(fresh); 91 | } 92 | 93 | /** 94 | * @param fresh 95 | * @return 96 | */ 97 | public static Type makeTypeVariable(String fresh) { 98 | Type t = new TypeVariable(fresh); 99 | bounds.put(fresh, t); 100 | return t; 101 | } 102 | 103 | /** 104 | * Reset start index for generating fresh names and cleans up 105 | * hashmap 106 | */ 107 | public static void reset() { 108 | bounds.clear(); 109 | freshIndex = 0; 110 | } 111 | 112 | } 113 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/core/ConstructorPattern.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright Arnaud Bailly, 2003-2013. All Rights Reserved. 3 | * 4 | 5 | * 6 | */ 7 | package fr.lifl.jaskell.compiler.core; 8 | 9 | import java.util.ArrayList; 10 | import java.util.Iterator; 11 | import java.util.List; 12 | 13 | import fr.lifl.jaskell.compiler.JaskellVisitor; 14 | 15 | 16 | /** 17 | * @author bailly 18 | * @version $Id: ConstructorPattern.java 1154 2005-11-24 21:43:37Z nono $ 19 | */ 20 | public class ConstructorPattern extends Pattern implements Cloneable { 21 | 22 | //~ ---------------------------------------------------------------------------------------------------------------- 23 | //~ Instance fields 24 | //~ ---------------------------------------------------------------------------------------------------------------- 25 | 26 | /** The constructor reference of this pattern */ 27 | private Constructor constructor; 28 | 29 | /** The list of sub-patterns */ 30 | private List patterns = new ArrayList(); 31 | 32 | //~ ---------------------------------------------------------------------------------------------------------------- 33 | //~ Constructors 34 | //~ ---------------------------------------------------------------------------------------------------------------- 35 | 36 | /** 37 | * Constructor for ConstructorPattern. 38 | */ 39 | public ConstructorPattern() { 40 | super(); 41 | } 42 | 43 | //~ ---------------------------------------------------------------------------------------------------------------- 44 | //~ Methods 45 | //~ ---------------------------------------------------------------------------------------------------------------- 46 | 47 | /** 48 | * @see jaskell.compiler.core.Expression#lookup(String) 49 | */ 50 | public Expression lookup(String vname) { 51 | Iterator it = getBindings().iterator(); 52 | while (it.hasNext()) { 53 | LocalBinding b = (LocalBinding) it.next(); 54 | if (b.getName().equals(vname)) 55 | return b; 56 | } 57 | return getParent().lookup(vname); 58 | } 59 | 60 | /** 61 | * Adds a new pattern to this pattern 62 | * 63 | * @param pat a Pattern object 64 | */ 65 | public void addPattern(Pattern pat) { 66 | patterns.add(pat); 67 | pat.setParent(this); 68 | } 69 | 70 | /** 71 | * @see jaskell.compiler.core.Pattern#getSubPatterns() 72 | */ 73 | public Iterator getSubPatterns() { 74 | return patterns.iterator(); 75 | } 76 | 77 | /** 78 | * Returns the constructor. 79 | * 80 | * @return Constructor 81 | */ 82 | public Constructor getConstructor() { 83 | return constructor; 84 | } 85 | 86 | /** 87 | * Sets the constructor. 88 | * 89 | * @param constructor The constructor to set 90 | */ 91 | public void setConstructor(Constructor constructor) { 92 | this.constructor = constructor; 93 | constructor.setParent(this); 94 | } 95 | 96 | /** 97 | * @see jaskell.compiler.core.Expression#visit(JaskellVisitor) 98 | */ 99 | public Object visit(JaskellVisitor v) { 100 | return v.visit(this); 101 | } 102 | 103 | /** 104 | * @see java.lang.Object#toString() 105 | */ 106 | public String toString() { 107 | StringBuffer sb = new StringBuffer("("); 108 | sb.append(constructor); 109 | Iterator it = patterns.iterator(); 110 | while (it.hasNext()) 111 | sb.append(' ').append(it.next()); 112 | return sb.append(")").toString(); 113 | 114 | } 115 | 116 | public Object clone() throws CloneNotSupportedException { 117 | ConstructorPattern cp = new ConstructorPattern(); 118 | cp.setConstructor((Constructor) constructor.clone()); 119 | Iterator it = patterns.iterator(); 120 | while (it.hasNext()) { 121 | Pattern pat = (Pattern) it.next(); 122 | cp.addPattern((Pattern) pat.clone()); 123 | } 124 | cp.setType(getType()); 125 | return cp; 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /src/test/java/fr/lifl/jaskell/compiler/CompilerPassTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright Arnaud Bailly, 2003-2013. All Rights Reserved. 3 | * 4 | 5 | * 6 | */ 7 | package fr.lifl.jaskell.compiler; 8 | 9 | import java.lang.reflect.Method; 10 | 11 | import fr.lifl.jaskell.compiler.bytecode.BytecodeGenerator; 12 | import fr.lifl.jaskell.compiler.core.Primitives; 13 | import fr.lifl.jaskell.compiler.types.Type; 14 | import fr.lifl.jaskell.compiler.types.Types; 15 | import fr.lifl.jaskell.runtime.modules.Prelude; 16 | import fr.lifl.jaskell.runtime.types.Closure; 17 | 18 | import junit.framework.TestCase; 19 | 20 | 21 | /** 22 | * @author bailly 23 | * @version $Id: CompilerPassTest.java 1183 2005-12-07 22:45:19Z nono $ 24 | */ 25 | public class CompilerPassTest extends TestCase { 26 | 27 | //~ ---------------------------------------------------------------------------------------------------------------- 28 | //~ Constructors 29 | //~ ---------------------------------------------------------------------------------------------------------------- 30 | 31 | /** 32 | * Constructor for PreludeTest. 33 | * 34 | * @param arg0 35 | */ 36 | public CompilerPassTest(String arg0) { 37 | super(arg0); 38 | } 39 | 40 | //~ ---------------------------------------------------------------------------------------------------------------- 41 | //~ Methods 42 | //~ ---------------------------------------------------------------------------------------------------------------- 43 | 44 | public void testEncodeName2Java() { 45 | String hname = "Toto.tutu.(..)$(++)"; 46 | String jname = "Toto/tutu/_2e_2e$_2b_2b"; 47 | String res = BytecodeGenerator.encodeName2Java(hname); 48 | assertEquals(jname, res); 49 | } 50 | 51 | public void testEncodeName2Java2() { 52 | String hname = "(++)"; 53 | String jname = "_2b_2b"; 54 | String res = BytecodeGenerator.encodeName2Java(hname); 55 | assertEquals(jname, res); 56 | } 57 | 58 | // simple case 59 | public void testEncodeFunctionName1() { 60 | Type t = Types.fun(Primitives.INT, Primitives.BOOL); 61 | String res = BytecodeGenerator.encodeName2Java(t.toString()); 62 | String jname = "Int_2d_3eBool"; 63 | assertEquals("Type " + t, jname, res); 64 | } 65 | 66 | public void testEncodeFunctionName2() { 67 | Type t = Types.fun(Types.fun(Primitives.INT, Primitives.INT), Primitives.BOOL); 68 | String res = BytecodeGenerator.encodeName2Java(t.toString()); 69 | String jname = "_28Int_2d_3eInt_29_2d_3eBool"; 70 | assertEquals("Type " + t, jname, res); 71 | } 72 | 73 | public void testEncodeFunctionName3() { 74 | Type t = Types.fun(Primitives.INT, Types.fun(Types.fun(Primitives.INT, Primitives.INT), Primitives.BOOL)); 75 | String res = BytecodeGenerator.encodeName2Java(t.toString()); 76 | String jname = "Int_2d_3e_28_28Int_2d_3eInt_29_2d_3eBool_29"; 77 | assertEquals("Type " + t, jname, res); 78 | } 79 | 80 | public void testEncodeType1() { 81 | Class[] cls1 = new Class[] { int.class }; 82 | Type f = Types.fun(Primitives.INT, Primitives.BOOL); 83 | Class[] cls2 = BytecodeGenerator.encodeType2Java(f); 84 | assertEquals(2, cls2.length); 85 | assertEquals(cls1[0], cls2[0]); 86 | } 87 | 88 | public void testEncodeType2() { 89 | Class[] cls1 = new Class[] { java.lang.String.class, Closure.class }; 90 | Type f = Types.fun(Primitives.STRING, Types.fun(Types.fun(Primitives.INT, Primitives.BOOL), Primitives.FLOAT)); 91 | Class[] cls2 = BytecodeGenerator.encodeType2Java(f); 92 | assertEquals(3, cls2.length); 93 | assertEquals(cls1[0], cls2[0]); 94 | assertEquals(cls1[1], cls2[1]); 95 | } 96 | 97 | // resolve addition on integers 98 | public void testResolve() throws Exception { 99 | String fname = "(+)"; 100 | Type f = Types.fun(Primitives.INT, Types.fun(Primitives.INT, Primitives.INT)); 101 | Method m = CompilerPass.resolvePrimitive(fname, f); 102 | Method expect = Prelude.class.getMethod("_2b", new Class[] { int.class, int.class }); 103 | assertEquals(expect, m); 104 | } 105 | 106 | } 107 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/datatypes/DataDefinition.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright Arnaud Bailly, 2003-2013. All Rights Reserved. 3 | * 4 | 5 | * 6 | */ 7 | package fr.lifl.jaskell.compiler.datatypes; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | import fr.lifl.jaskell.compiler.CompilerException; 13 | import fr.lifl.jaskell.compiler.JaskellVisitor; 14 | import fr.lifl.jaskell.compiler.core.Definition; 15 | import fr.lifl.jaskell.compiler.core.Module; 16 | import fr.lifl.jaskell.compiler.types.*; 17 | 18 | 19 | /** 20 | * @author bailly 21 | * @version $Id: DataDefinition.java 1154 2005-11-24 21:43:37Z nono $ 22 | */ 23 | public class DataDefinition extends Definition { 24 | 25 | //~ ---------------------------------------------------------------------------------------------------------------- 26 | //~ Instance fields 27 | //~ ---------------------------------------------------------------------------------------------------------------- 28 | 29 | /* list of constructors for data type */ 30 | private List constructors; 31 | 32 | /* list of type paremeters */ 33 | private List parameters; 34 | 35 | /* type constructor expression */ 36 | private Type type; 37 | 38 | /* kind of this constructor */ 39 | private Kind kind; 40 | 41 | //~ ---------------------------------------------------------------------------------------------------------------- 42 | //~ Constructors 43 | //~ ---------------------------------------------------------------------------------------------------------------- 44 | 45 | /** 46 | * Constructor for DataDefinition. 47 | */ 48 | public DataDefinition(String name, Module mod) { 49 | this(name, Types.makeTycon(name), mod); 50 | } 51 | 52 | /** 53 | * Constructs a data definition with a simple type. The given type argument must be application of a type 54 | * constructor to zero or more type variables 55 | * 56 | * @param t a Type 57 | * @param mod Module where this definition is stored 58 | */ 59 | public DataDefinition(String name, Type t, Module mod) { 60 | super(name, null, null, mod); 61 | if (t instanceof TypeApplication) { 62 | TypeConstructor tc = (TypeConstructor) t.getConstructor(); 63 | /* construct kind */ 64 | this.kind = tc.getKind(); 65 | } else if (t instanceof TypeConstructor) { 66 | this.kind = SimpleKind.K; 67 | } else 68 | throw new CompilerException("Invalid type argument for data definition :" + t.makeString() + " type = " + t.getClass()); 69 | this.type = t; 70 | this.constructors = new ArrayList(); 71 | this.parameters = new ArrayList(); 72 | mod.addTypeDefinition(this); 73 | //mod.bind(name, this); 74 | } 75 | 76 | //~ ---------------------------------------------------------------------------------------------------------------- 77 | //~ Methods 78 | //~ ---------------------------------------------------------------------------------------------------------------- 79 | 80 | /** 81 | * Adds a new constructor for this data type 82 | * 83 | * @param cdef a Constructor definition object 84 | */ 85 | public void addConstructor(ConstructorDefinition cdef) { 86 | constructors.add(cdef); 87 | cdef.setParent(this); 88 | } 89 | 90 | /** 91 | * Return the set of constructors for this data type 92 | * 93 | * @return a - possibly empty - list 94 | */ 95 | public List getConstructors() { 96 | return constructors; 97 | } 98 | 99 | public Object visit(JaskellVisitor v) { 100 | return v.visit(this); 101 | } 102 | 103 | public Type getType() { 104 | return type; 105 | } 106 | 107 | /** 108 | * @see java.lang.Object#toString() 109 | */ 110 | public String toString() { 111 | return type.makeString(); 112 | } 113 | 114 | /** 115 | * @see java.lang.Object#equals(Object) 116 | */ 117 | public boolean equals(Object obj) { 118 | if (!(obj instanceof DataDefinition)) 119 | return false; 120 | return getName().equals(((DataDefinition) obj).getName()); 121 | } 122 | 123 | } 124 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/core/LocalBinding.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.compiler.core; 2 | 3 | import fr.lifl.jaskell.compiler.JaskellVisitor; 4 | import fr.lifl.jaskell.compiler.types.Type; 5 | 6 | import java.util.ArrayList; 7 | import java.util.Iterator; 8 | import java.util.List; 9 | import java.util.WeakHashMap; 10 | 11 | /** 12 | * This class contains name and type bindings 13 | * 14 | * @author bailly 15 | * @version $Id: LocalBinding.java 1154 2005-11-24 21:43:37Z nono $ 16 | * */ 17 | public class LocalBinding extends Pattern implements Binding { 18 | 19 | private static final String freshPrefix = "v"; 20 | 21 | private static int freshIndex = 0; 22 | 23 | /* map of all bindings already defined - to create fresh variables */ 24 | private static WeakHashMap bounds = new WeakHashMap(); 25 | 26 | /** catch-all binding */ 27 | public static final LocalBinding wildcard = new LocalBinding("_"); 28 | 29 | /** name of variable */ 30 | private String name; 31 | 32 | /** index of variable */ 33 | private int index; 34 | 35 | /** strictness of variable */ 36 | private boolean strict; 37 | 38 | /** 39 | * Constructs a new binding given a name and a type 40 | * 41 | * @param name name of this binding 42 | * @param type type of this binding. May be null 43 | */ 44 | public LocalBinding(String name, Type type) { 45 | this(name); 46 | this.type = type; 47 | } 48 | 49 | /** 50 | * Constructor LocalBinding. 51 | * @param string 52 | */ 53 | public LocalBinding(String name) { 54 | this.name = name; 55 | bounds.put(name,this); 56 | } 57 | 58 | /** 59 | * Returns the name. 60 | * @return String 61 | */ 62 | public String getName() { 63 | return name; 64 | } 65 | 66 | 67 | /** 68 | * Returns the index. 69 | * @return int 70 | */ 71 | public int getIndex() { 72 | return index; 73 | } 74 | 75 | /** 76 | * Sets the index. 77 | * @param index The index to set 78 | */ 79 | public void setIndex(int index) { 80 | this.index = index; 81 | } 82 | 83 | /** 84 | * Sets the name. 85 | * @param name The name to set 86 | */ 87 | public void setName(String name) { 88 | this.name = name; 89 | } 90 | 91 | /** 92 | * Returns the strict. 93 | * @return boolean 94 | */ 95 | public boolean isStrict() { 96 | return strict; 97 | } 98 | 99 | /** 100 | * Sets the strict. 101 | * @param strict The strict to set 102 | */ 103 | public void setStrict(boolean strict) { 104 | this.strict = strict; 105 | } 106 | 107 | /** 108 | * @see jaskell.compiler.core.Pattern#getSubPatterns() 109 | */ 110 | public Iterator getSubPatterns() { 111 | return new EmptyIterator(); 112 | } 113 | 114 | /** 115 | * @see jaskell.compiler.core.Expression#visit(JaskellVisitor) 116 | */ 117 | public Object visit(JaskellVisitor v) { 118 | return v.visit(this); 119 | } 120 | 121 | /** 122 | * @see jaskell.compiler.core.Pattern#countBindings() 123 | */ 124 | public int countBindings() { 125 | return 1; 126 | } 127 | 128 | /** 129 | * @see jaskell.compiler.core.Pattern#getBindings() 130 | */ 131 | public List getBindings() { 132 | List l = new ArrayList(); 133 | l.add(this); 134 | return l; 135 | } 136 | 137 | /** 138 | * @see jaskell.compiler.core.Expression#lookup(String) 139 | */ 140 | public Expression lookup(String vname) { 141 | if (vname.equals(name)) 142 | return this; 143 | return getParent().lookup(vname); 144 | } 145 | 146 | /** 147 | * @see jaskell.compiler.core.Binding#getDefinition() 148 | */ 149 | public Expression getDefinition() { 150 | return null; 151 | } 152 | 153 | /** 154 | * Method freshBinding. 155 | * @return LocalBinding 156 | */ 157 | public static LocalBinding freshBinding() { 158 | String fresh = freshPrefix + freshIndex; 159 | while(bounds.get(fresh) != null) fresh = freshPrefix + ++freshIndex; 160 | return new LocalBinding(fresh); 161 | } 162 | 163 | /** 164 | * @see java.lang.Object#toString() 165 | */ 166 | public String toString() { 167 | return name; 168 | } 169 | 170 | /* (non-Javadoc) 171 | * @see java.lang.Object#clone() 172 | */ 173 | public Object clone() { 174 | LocalBinding lb =new LocalBinding(name,getType()); 175 | lb.setIndex(index); 176 | lb.setStrict(strict); 177 | return lb; 178 | } 179 | 180 | } 181 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/Main.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on Jun 5, 2003 by Arnaud Bailly - bailly@lifl.fr 3 | * Copyright 2003 - Arnaud Bailly 4 | * $Log: Main.java,v $ 5 | * Revision 1.6 2004/02/09 20:40:02 nono 6 | * mise a jour repository central 7 | * 8 | * Revision 1.5 2003/06/23 06:33:31 bailly 9 | * Debugging 10 | * Added JError primitive type to raise runtime exceptions 11 | * when no match is found 12 | * 13 | */ 14 | package fr.lifl.jaskell.compiler; 15 | 16 | import fr.lifl.jaskell.compiler.bytecode.ClassFileWriter; 17 | import fr.lifl.jaskell.compiler.bytecode.CodeGenerator; 18 | import fr.lifl.jaskell.compiler.bytecode.Type2Class; 19 | import fr.lifl.jaskell.compiler.core.Module; 20 | import fr.lifl.jaskell.parser.ParseException; 21 | import fr.lifl.jaskell.parser.Yyparser; 22 | 23 | import java.util.Iterator; 24 | 25 | /** 26 | * The main program for compiling Jaskell sources 27 | * 28 | * This is the class holding the main program for compiling jaskell 29 | * sources into java bytecode 30 | * 31 | * @author bailly 32 | * @version $Id: Main.java 1154 2005-11-24 21:43:37Z nono $ 33 | */ 34 | public class Main { 35 | 36 | public static void usage() { 37 | System.err.println( 38 | "java -jar jaskell.jar (-I )* [-v] [-d ] .. "); 39 | System.exit(1); 40 | } 41 | 42 | public static void main(String argv[]) throws ClassNotFoundException { 43 | /* list of files to process */ 44 | java.util.List files = new java.util.ArrayList(); 45 | /* list of directories to look for import directives */ 46 | java.util.List includes = new java.util.ArrayList(); 47 | /* output directory */ 48 | String outdir = "."; 49 | /* verbos output flag */ 50 | boolean verbose = false; 51 | 52 | if (argv.length < 1) 53 | usage(); 54 | /* parse command line */ 55 | for (int i = 0; i < argv.length; i++) 56 | if (argv[i].startsWith("-")) // command-line option 57 | switch (argv[i].charAt(1)) { 58 | case 'I' : // include directory 59 | includes.add(argv[++i]); 60 | break; 61 | case 'd' : // output stream 62 | outdir = argv[++i]; 63 | break; 64 | case 'v' : // verbose processing 65 | verbose = true; 66 | break; 67 | default : 68 | System.err.println("Unknown option :" + argv[i]); 69 | usage(); 70 | } else 71 | files.add(argv[i]); 72 | 73 | /* process include directives */ 74 | Iterator it = includes.iterator(); 75 | StringBuffer incprop = new StringBuffer(""); 76 | while (it.hasNext()) { 77 | incprop.append((String) it.next()); 78 | if (it.hasNext()) 79 | incprop.append(':'); 80 | } 81 | String incstr = null; 82 | if (!incprop.toString().equals("")) 83 | incstr = incprop.toString(); 84 | /* process files */ 85 | Yyparser parser = new Yyparser(verbose); 86 | it = files.iterator(); 87 | while (it.hasNext()) { 88 | java.io.FileInputStream instr = null; 89 | String fname = (String) it.next(); 90 | if (verbose) 91 | System.err.println("Processing file " + fname); 92 | /* open file */ 93 | try { 94 | parser.parse(fname); 95 | } catch (ParseException pex) { 96 | System.err.println( 97 | "Error while parsing " + fname + " : " + pex.getMessage()); 98 | continue; 99 | } 100 | } 101 | 102 | /* generate code */ 103 | /* load prelude */ 104 | Class prim = Class.forName("jaskell.compiler.core.Primitives"); 105 | 106 | Iterator modit = parser.getModules().iterator(); 107 | while (modit.hasNext()) { 108 | Module m = (Module) modit.next(); 109 | if (verbose) { 110 | System.err.println("Generating code for module :"); 111 | System.err.println(m.toString()); 112 | 113 | } 114 | /* generate types */ 115 | Type2Class t2c = new Type2Class(m); 116 | //m.visit(t2c); 117 | /* generate code */ 118 | LambdaLifter ll = new LambdaLifter(m); 119 | StrictnessAnalyzer sa = new StrictnessAnalyzer(); 120 | TypeChecker tc = new TypeChecker(); 121 | CodeGenerator cg = new CodeGenerator(); 122 | /* work ! */ 123 | m.visit(ll); 124 | m.visit(sa); 125 | m.visit(tc); 126 | /* generate types */ 127 | m.visit(t2c); 128 | /* generate code */ 129 | m.visit(cg); 130 | /* write */ 131 | ClassFileWriter writer = new ClassFileWriter(outdir); 132 | CodeGenerator.cleanupClassFiles(writer); 133 | Type2Class.cleanupClassFiles(writer); 134 | if (verbose) 135 | System.err.println(m); 136 | } 137 | /* done */ 138 | } 139 | 140 | } 141 | -------------------------------------------------------------------------------- /src/test/java/fr/lifl/jaskell/compiler/CompilerTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright Arnaud Bailly, 2003-2013. All Rights Reserved. 3 | * 4 | 5 | * 6 | */ 7 | package fr.lifl.jaskell.compiler; 8 | 9 | import java.lang.reflect.Method; 10 | 11 | import fr.lifl.jaskell.compiler.bytecode.BytecodeGenerator; 12 | import fr.lifl.jaskell.compiler.bytecode.ClassFileWriter; 13 | import fr.lifl.jaskell.compiler.bytecode.CodeGenerator; 14 | import fr.lifl.jaskell.compiler.bytecode.Type2Class; 15 | import fr.lifl.jaskell.compiler.core.Abstraction; 16 | import fr.lifl.jaskell.compiler.core.Application; 17 | import fr.lifl.jaskell.compiler.core.Conditional; 18 | import fr.lifl.jaskell.compiler.core.IntegerLiteral; 19 | import fr.lifl.jaskell.compiler.core.LocalBinding; 20 | import fr.lifl.jaskell.compiler.core.Module; 21 | import fr.lifl.jaskell.compiler.core.Primitives; 22 | import fr.lifl.jaskell.compiler.core.QualifiedVariable; 23 | import fr.lifl.jaskell.compiler.core.Variable; 24 | import fr.lifl.jaskell.compiler.types.Type; 25 | 26 | import junit.framework.TestCase; 27 | 28 | import oqube.bytes.loading.ClassFileLoader; 29 | 30 | 31 | /** 32 | * @author bailly 33 | * @version $Id: CompilerTest.java 1183 2005-12-07 22:45:19Z nono $ 34 | */ 35 | public class CompilerTest extends TestCase { 36 | 37 | static { 38 | BytecodeGenerator.setLoader(new ClassFileLoader(ClassLoader.getSystemClassLoader())); 39 | } 40 | 41 | 42 | /** 43 | * Constructor for CompilerTest. 44 | * 45 | * @param arg0 46 | */ 47 | public CompilerTest(String arg0) { 48 | super(arg0); 49 | } 50 | 51 | //~ ---------------------------------------------------------------------------------------------------------------- 52 | //~ Methods 53 | //~ ---------------------------------------------------------------------------------------------------------------- 54 | 55 | public void testFac() throws Exception { 56 | Module m = new Module("Main", null); 57 | Type t = Primitives.INT; /* for loading primitives */ 58 | // definition de g 59 | Abstraction a1 = new Abstraction(); 60 | a1.bind(new LocalBinding("x")); 61 | 62 | Application ap0 = new Application(); 63 | QualifiedVariable qv = new QualifiedVariable("(*)"); 64 | qv.addPathElement("Prelude"); 65 | ap0.setFunction(qv); 66 | ap0.addArgument(new Variable("x")); 67 | 68 | Application ap1 = new Application(); 69 | Variable v = new Variable("fac"); 70 | ap1.setFunction(v); 71 | Application ap2 = new Application(); 72 | qv = new QualifiedVariable("(-)"); 73 | qv.addPathElement("Prelude"); 74 | ap2.setFunction(qv); 75 | ap2.addArgument(new Variable("x")); 76 | ap2.addArgument(new IntegerLiteral(1)); 77 | ap1.addArgument(ap2); 78 | ap0.addArgument(ap1); 79 | 80 | Application ap3 = new Application(); 81 | qv = new QualifiedVariable("(==)"); 82 | qv.addPathElement("Prelude"); 83 | ap3.setFunction(qv); 84 | ap3.addArgument(new Variable("x")); 85 | ap3.addArgument(new IntegerLiteral(0)); 86 | 87 | Conditional if1 = new Conditional(); 88 | if1.setCondition(ap3); 89 | if1.setIfTrue(new IntegerLiteral(1)); 90 | if1.setIfFalse(ap0); 91 | a1.setBody(if1); 92 | // definition de f 93 | m.bind("fac", a1); 94 | Application ap4 = new Application(); 95 | ap4.setFunction(new Variable("fac")); 96 | ap4.addArgument(new IntegerLiteral(5)); 97 | Application ap5 = new Application(); 98 | QualifiedVariable qv1 = new QualifiedVariable("primPutInt"); 99 | qv1.addPathElement("Prelude"); 100 | ap5.setFunction(qv1); 101 | ap5.addArgument(ap4); 102 | m.bind("main", ap5); 103 | StrictnessAnalyzer sal = new StrictnessAnalyzer(); 104 | TypeChecker tc = new TypeChecker(); 105 | CodeGenerator gen = new CodeGenerator(); 106 | m.visit(tc); 107 | m.visit(sal); 108 | m.visit(gen); 109 | ClassFileLoader writer = (ClassFileLoader) BytecodeGenerator.getLoader(); 110 | BytecodeGenerator.cleanupClassFiles(writer); 111 | /* resolve Main class and call myMax */ 112 | Class cls = writer.loadClass("Main$Module"); 113 | assertNotNull(cls); 114 | Method met = cls.getMethod("fac", null); 115 | assertNotNull(met); 116 | Object obj = met.invoke(null, null); 117 | Class facClass = obj.getClass(); 118 | met = facClass.getMethod("eval", new Class[]{int.class}); 119 | obj = met.invoke(obj, new Object[] { new Integer(4) }); 120 | assertEquals(24, ((Integer) obj).intValue()); 121 | } 122 | 123 | } 124 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/runtime/types/JValue.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.runtime.types; 2 | 3 | import java.lang.reflect.Field; 4 | 5 | /** 6 | * Base class for all concrete values 7 | * 8 | * @author bailly 9 | * @version $Id: JValue.java 1153 2005-11-24 20:47:55Z nono $ 10 | */ 11 | public abstract class JValue implements JObject,JFunction { 12 | 13 | /* number of applied arguments for constructors */ 14 | private int nargs = 0; 15 | 16 | 17 | /** 18 | * Evaluates this objects, yielding a supposedly reduced 19 | * object. The implementation iin JObject does nothing and 20 | * returns this. 21 | * 22 | * @return a JObject which is guaranteed to be the same object 23 | * or a reduced form of this. 24 | */ 25 | public JObject eval() { 26 | return this; 27 | } 28 | 29 | /** 30 | * Evaluates this object as an integer 31 | * 32 | * @return an int resulting from the evaluation of this. 33 | * @exception IllegalStateException if this object cannot be 34 | * reduced to an int value 35 | */ 36 | public int asInt() { 37 | throw new IllegalStateException("JObject may not be evaluated as int"); 38 | } 39 | 40 | /** 41 | * Evaluates this object as a float 42 | * 43 | * @return a float resulting from the evaluation of this. 44 | * @exception IllegalStateException if this object cannot be 45 | * reduced to a float value 46 | */ 47 | public float asFloat() { 48 | throw new IllegalStateException("JObject may not be evaluated as float"); 49 | } 50 | 51 | /** 52 | * Evaluates this object as a double 53 | * 54 | * @return a double resulting from the evaluation of this. 55 | * @exception IllegalStateException if this object cannot be 56 | * reduced to a double value 57 | */ 58 | public double asDouble() { 59 | throw new IllegalStateException("JObject may not be evaluated as double"); 60 | } 61 | 62 | /** 63 | * Evaluates this object as a char 64 | * 65 | * @return a char resulting from the evaluation of this. 66 | * @exception IllegalStateException if this object cannot be 67 | * reduced to a char value 68 | */ 69 | public char asChar() { 70 | throw new IllegalStateException("JObject may not be evaluated as char"); 71 | } 72 | 73 | /** 74 | * Evaluates this object as a String 75 | * 76 | * @return a String resulting from the evaluation of this. 77 | * @exception IllegalStateException if this object cannot be 78 | * reduced to a String value 79 | */ 80 | public java.lang.String asString() { 81 | throw new IllegalStateException("JObject may not be evaluated as java.lang.String"); 82 | } 83 | 84 | /** 85 | * Evaluates this object as a boolean 86 | * 87 | * @return a boolean resulting from the evaluation of this. 88 | * @exception IllegalStateException if this object cannot be 89 | * reduced to a boolean value 90 | */ 91 | public boolean asBool() { 92 | throw new IllegalStateException("JObject may not be evaluated as boolean"); 93 | } 94 | 95 | 96 | /* (non-Javadoc) 97 | * @see jaskell.runtime.types.JFunction#apply(jaskell.runtime.types.JObject) 98 | */ 99 | public JObject apply(JObject obj) { 100 | /* retrieve field with name equals to nargs */ 101 | String fn = "_"+nargs; 102 | Class cls = this.getClass(); 103 | try { 104 | Field fld = cls.getField(fn); 105 | Class fcls = fld.getType(); 106 | if(!fcls.equals(JObject.class)) { /* strict arguments */ 107 | /* handle unboxed types */ 108 | if(fcls.equals(int.class)) { 109 | fld.set(this,new Integer(((JValue)obj).asInt())); 110 | } else if(fcls.equals(char.class)) { 111 | fld.set(this,new Character(((JValue)obj).asChar())); 112 | }else if(fcls.equals(float.class)) { 113 | fld.set(this,new Float(((JValue)obj).asFloat())); 114 | }else if(fcls.equals(double.class)) { 115 | fld.set(this,new Double(((JValue)obj).asDouble())); 116 | }else if(fcls.equals(boolean.class)) { 117 | fld.set(this,new Boolean(((JValue)obj).asBool())); 118 | }else if(fcls.equals(String.class)) { 119 | fld.set(this,((JValue)obj).asString()); 120 | }else { 121 | fld.set(this,obj); 122 | } 123 | } else { 124 | fld.set(this,obj); 125 | } 126 | nargs++; 127 | } catch (Exception e) { 128 | throw new 129 | IllegalArgumentException("Too many arguments applied"); 130 | } 131 | return this; 132 | } 133 | 134 | /* Returns an empty instance of this object 135 | * @see jaskell.runtime.types.JFunction#init() 136 | */ 137 | public JFunction init() { 138 | Class cls = this.getClass(); 139 | try { 140 | return (JFunction)cls.newInstance(); 141 | } catch (Exception e) { 142 | throw new IllegalStateException("Cannot create instance of "+cls.getName()); 143 | } 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/types/TypeApplication.java: -------------------------------------------------------------------------------- 1 | package fr.lifl.jaskell.compiler.types; 2 | 3 | 4 | /** 5 | * This class represents application of a type to another type 6 | * 7 | * @author bailly 8 | * @version $Id: TypeApplication.java 1153 2005-11-24 20:47:55Z nono $ 9 | */ 10 | public class TypeApplication extends Type { 11 | 12 | private Type domain; 13 | private Type range; 14 | 15 | /** 16 | * Constructor for TypeApplication. 17 | */ 18 | TypeApplication(Type domain, Type range) { 19 | /* check kind */ 20 | checkKind(domain, range); 21 | this.domain = domain; 22 | this.range = range; 23 | } 24 | 25 | /** 26 | * Method checkKind. 27 | *

28 | * This method verifies that the type domain can be applied to 29 | * the type range 30 | * 31 | * @param domain 32 | * @param range 33 | */ 34 | public static void checkKind(Type domain, Type range) { 35 | try { 36 | Kind kd = domain.getKind(); 37 | Kind kr = range.getKind(); 38 | /* range is a type variable without kind - set it to * */ 39 | if (kr == null) 40 | range.setKind(SimpleKind.K); 41 | if (kd == null) /* set kind of domain to account for range */ 42 | domain.setKind(new FunctionKind(SimpleKind.K, range.getKind())); 43 | return; 44 | } catch (ClassCastException cex) { 45 | throw new TypeError( 46 | "Invalid type application from type " 47 | + domain.toString() 48 | + "(" 49 | + domain.getKind() 50 | + ")" 51 | + " to " 52 | + range.toString() 53 | + "(" 54 | + range.getKind() 55 | + ")"); 56 | } 57 | 58 | } 59 | 60 | public T visit(TypeVisitor v) { 61 | return v.visit(this); 62 | } 63 | 64 | public boolean contains(TypeVariable variableType) { 65 | return domain.contains(variableType) || range.contains(variableType); 66 | } 67 | 68 | /** 69 | * Returns the domain. 70 | * 71 | * @return Type 72 | */ 73 | public Type getDomain() { 74 | return domain; 75 | } 76 | 77 | /** 78 | * Returns the range. 79 | * 80 | * @return Type 81 | */ 82 | public Type getRange() { 83 | return range; 84 | } 85 | 86 | public Kind getKind() { 87 | try { 88 | return domain.getKind().apply(getRange().getKind()); 89 | } catch (NullPointerException npex) { 90 | return null; 91 | } 92 | } 93 | 94 | /** 95 | * @see java.lang.Object#toString() 96 | */ 97 | public String toString() { 98 | String format = domain.getApplyFormatter().formatApply(domain, range); 99 | if (getKind() == SimpleKind.K) 100 | return "(" + format + ")"; 101 | return format; 102 | 103 | } 104 | 105 | public Type getConstructor() { 106 | Type t = domain; 107 | while (t instanceof TypeApplication) 108 | t = ((TypeApplication) t).getDomain(); 109 | return t; 110 | } 111 | 112 | 113 | /** 114 | * @see java.lang.Object#equals(Object) 115 | */ 116 | public boolean equals(Object obj) { 117 | if (!(obj instanceof TypeApplication)) 118 | return false; 119 | TypeApplication ta = (TypeApplication) obj; 120 | return domain.equals(ta.domain) && range.equals(ta.range); 121 | } 122 | 123 | /** 124 | * This method is called by checkKind to infer the kind of a domain of 125 | * an application. 126 | */ 127 | public void setKind(Kind kind) { 128 | domain.setKind(new FunctionKind(range.getKind(), kind)); 129 | } 130 | 131 | /* (non-Javadoc) 132 | * @see jaskell.compiler.types.Type#setContext(jaskell.compiler.core.Expression) 133 | */ 134 | public void setContext(TypeContext expression) { 135 | domain.setContext(expression); 136 | range.setContext(expression); 137 | } 138 | 139 | /* (non-Javadoc) 140 | * @see jaskell.compiler.types.Type#compare(jaskell.compiler.types.Type) 141 | */ 142 | public int compare(Type other) throws UncomparableException { 143 | try { 144 | TypeApplication ta = (TypeApplication) other; 145 | if (this.getConstructor().compare(ta.getConstructor()) == 0) 146 | return Type.getComparatorFor(this.getConstructor()).compare(this, other); 147 | else 148 | throw new UncomparableException("Cannot compare " + this + " with " + other); 149 | } catch (ClassCastException ccex) { 150 | /* other is not a ta - maybe a variable */ 151 | return other.compare(this); 152 | } 153 | } 154 | 155 | } 156 | -------------------------------------------------------------------------------- /src/main/java/fr/lifl/jaskell/compiler/CaptureCollector.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright Arnaud Bailly, 2003-2013. All Rights Reserved. 3 | * 4 | 5 | * 6 | */ 7 | package fr.lifl.jaskell.compiler; 8 | 9 | import java.util.HashSet; 10 | import java.util.Iterator; 11 | import java.util.Set; 12 | 13 | import fr.lifl.jaskell.compiler.core.*; 14 | 15 | 16 | /** 17 | * A class that collects a Set of captured variables 18 | * 19 | * @author bailly 20 | * @version $Id: CaptureCollector.java 1154 2005-11-24 21:43:37Z nono $ 21 | */ 22 | class CaptureCollector extends JaskellVisitorAdapter { 23 | 24 | //~ ---------------------------------------------------------------------------------------------------------------- 25 | //~ Instance fields 26 | //~ ---------------------------------------------------------------------------------------------------------------- 27 | 28 | private final Set emptySet = new HashSet(); 29 | 30 | /* the set of captured variables */ 31 | private Set captured; 32 | 33 | /* the set of locally bound variables */ 34 | private Set locals; 35 | 36 | //~ ---------------------------------------------------------------------------------------------------------------- 37 | //~ Constructors 38 | //~ ---------------------------------------------------------------------------------------------------------------- 39 | 40 | /** 41 | */ 42 | public CaptureCollector() { 43 | this.captured = new HashSet(); 44 | this.locals = new HashSet(); 45 | } 46 | 47 | /** 48 | * @param captured 49 | */ 50 | public CaptureCollector(Set captured) { 51 | this.captured = captured; 52 | this.locals = new HashSet(); 53 | } 54 | 55 | //~ ---------------------------------------------------------------------------------------------------------------- 56 | //~ Methods 57 | //~ ---------------------------------------------------------------------------------------------------------------- 58 | 59 | /* (non-Javadoc) 60 | * @see jaskell.compiler.JaskellVisitor#visit(jaskell.compiler.core.Abstraction) 61 | */ 62 | public Object visit(Abstraction a) { 63 | locals.addAll(a.getBindings().values()); 64 | a.getBody().visit(this); 65 | return null; 66 | } 67 | 68 | /* (non-Javadoc) 69 | * @see jaskell.compiler.JaskellVisitor#visit(jaskell.compiler.core.Alternative) 70 | */ 71 | public Object visit(Alternative a) { 72 | /* add all bindings to locals */ 73 | locals.add(a.getBinding()); 74 | Iterator it = a.getPatterns(); 75 | while (it.hasNext()) { 76 | locals.addAll(((Pattern) it.next()).getBindings()); 77 | } 78 | /* visit all bodies of alternative */ 79 | it = a.getBodies(); 80 | while (it.hasNext()) { 81 | Expression e = (Expression) it.next(); 82 | e.visit(this); 83 | } 84 | return null; 85 | } 86 | 87 | /* (non-Javadoc) 88 | * @see jaskell.compiler.JaskellVisitor#visit(jaskell.compiler.core.Application) 89 | */ 90 | 91 | public Object visit(Application a) { 92 | a.getFunction().visit(this); 93 | /* visit all bodies of alternative */ 94 | Iterator it = a.getArgs().iterator(); 95 | while (it.hasNext()) { 96 | Expression e = (Expression) it.next(); 97 | e.visit(this); 98 | } 99 | return null; 100 | } 101 | 102 | /* (non-Javadoc) 103 | * @see jaskell.compiler.JaskellVisitor#visit(jaskell.compiler.core.Conditional) 104 | */ 105 | public Object visit(Conditional conditional) { 106 | conditional.getCondition().visit(this); 107 | conditional.getIfFalse().visit(this); 108 | conditional.getIfTrue().visit(this); 109 | return null; 110 | } 111 | 112 | /* (non-Javadoc) 113 | * @see jaskell.compiler.JaskellVisitor#visit(jaskell.compiler.core.Definition) 114 | */ 115 | public Object visit(Definition a) { 116 | return a.getDefinition().visit(this); 117 | } 118 | 119 | /* (non-Javadoc) 120 | * @see jaskell.compiler.JaskellVisitor#visit(jaskell.compiler.core.Let) 121 | */ 122 | public Object visit(Let let) { 123 | Iterator it = let.getBindings().values().iterator(); 124 | while (it.hasNext()) { 125 | Expression e = (Expression) it.next(); 126 | e.visit(this); 127 | } 128 | return null; 129 | } 130 | 131 | /* (non-Javadoc) 132 | * @see jaskell.compiler.JaskellVisitor#visit(jaskell.compiler.core.Variable) 133 | */ 134 | public Object visit(Variable a) { 135 | /* resolve variable */ 136 | Expression e = a.lookup(a.getName()); 137 | /* simple case */ 138 | if (locals.contains(e) || !(e instanceof LocalBinding)) { 139 | return emptySet; 140 | } 141 | /* e is defined in outer scope */ 142 | captured.add(e); 143 | return null; 144 | } 145 | 146 | } 147 | --------------------------------------------------------------------------------