// FILE. . . . . /home/hak/hlt/src/hlt/language/jaccapps/aql/test/bug/Bug.java
// EDIT BY . . . Hassan Ait-Kaci
// ON MACHINE. . Hp-Dv7
// STARTED ON. . Sat Oct 20 02:50:23 2012

// Last modified on Sat Oct 20 02:53:11 2012 by hak

// expr = let b:int[int] = let !a:[int][int] = [int][2]; in { !a[0] = 1; !a[1] = 2; !a; }; in ()

// exp = let b:int[int] = let !a:[int][int] = B[2]; in { !a[0] = 1; !a[1] = 2; !a; }; in ()

import hlt.language.design.kernel.*;
import hlt.language.design.kernel.Compiler;
import hlt.language.design.types.*;
import hlt.language.runtime.Runtime;

import java.util.ArrayList;

class Bug
{
    public static void main(String[] args) throws java.lang.Exception
    {
        Expression exp = bugged();
//      Expression exp = arrayExtension();

        compile(exp);
        System.out.println("exp = " + exp);

        Runtime runtime = new Runtime();
        runtime.run(compiler.code());
    }

    static Tables tables = new Tables();

    static Expression let (String parameter, Type type, Expression value, Expression body)
    {
        ArrayList parameters = new ArrayList();
        ArrayList types = new ArrayList();
        ArrayList values = new ArrayList();
        parameters.add(parameter);
        types.add(type);
        values.add(value);
        return new Let(parameters, types, values, body);
    }

    // returns: 
    // let a:A[int] = A[2] in { a[0] = 1; a[1] = 2; a; }
    static Expression arrayExtension()
    {
        ArrayList elements = new ArrayList();
        elements.add(new Int(1));
        elements.add(new Int(2));
        ArrayList stmts = new ArrayList();
        for(int i=0; i<elements.size(); i++) {
            stmts.add(new ArraySlotUpdate(
                             new ArraySlot(new Dummy(tables, "!a"), 
                                           new Int(i)), 
                             (Expression)elements.get(i)));
        }
        stmts.add(new Dummy(tables, "!a"));
        Expression[] dims = new Expression[1];
        dims[0] = new Int(elements.size());
        TypeParameter baseType = new TypeParameter();
        Expression res = let("!a",
                             new ArrayType(baseType, Type.INT()),
                             new NewArray(baseType, dims),
                             new Sequence(stmts));
        return res;
    }

    // returns:
    // let b:int[int] = <arrayExtension()> in write(b)
    static Expression bugged()
    {
        ArrayList parameters = new ArrayList();
        ArrayList types = new ArrayList();
        ArrayList values = new ArrayList();

        Expression exp = let("b",
                             new ArrayType(Type.INT(), Type.INT()),
                             arrayExtension(),
                             Constant.VOID());
        return exp;
                                 
    }

    static Sanitizer sanitizer = new Sanitizer();
    static TypeChecker typeChecker = new TypeChecker();
    static Compiler compiler = new Compiler();

    static final Expression compile (Expression expression)
    {
        expression = uncaughtCompile(expression);
        return expression;
    }

    static final Expression uncaughtCompile (Expression expression) throws StaticSemanticsErrorException 
    {
     expression = sanitizer.sanitizeNames(expression);

     expression.typeCheck(typeChecker.reset());
     expression.setCheckedType();

     System.out.println("compiled expr = " + expression.toString());

     ArrayList types = new ArrayList();
     types.add(expression.checkedType());

     typeChecker.remainingTypes(expression,types);
     if (types.size() > 1)
         throw new java.lang.Error("ambiguous typing");

     if (expression instanceof Definition)
       {
         Definition def = (Definition)expression;
//          checkGlobalUnsafe(def.symbol().name(),def.checkedType());
         def.registerCodeEntry();
       }

     sanitizer.sanitizeSorts(expression);
     compiler.compile(expression);
     return expression;
    }      

}





