//==============================================================================
//  Creates Struct data
//==============================================================================
unit Structs00;

//==============================================================================
//  INTERFACE
//==============================================================================
interface

procedure Step00(var nativesblock: string);

//==============================================================================
//  IMPLEMENTATION
//==============================================================================
implementation
uses StructVariables, StringHash, JHInput, TextOnly, TextCommon, SysUtils,
    JASSerException, JStruct, Translate, Constants, Member, Jasslib, Prototypes,
    Classes;

//==============================================================================
procedure correctArraySize(const lnum:integer; const arsize:integer; const extended:boolean=false);
begin
    if(arsize=-3) then raise JAsserLineException(lnum,'Expected [size].');
    if(arsize=-1) then raise JAsserLineException(lnum,'Wrong [size] definition.');
    if(arsize<0) then raise JasserLineException(lnum,'Negative array size?');
    if(arsize=0) then raise JasserLineException(lnum,'Zero array size?');
    if(extended) then begin
        if(arsize>VJASS_MAX_ARRAY_INDEXES) then raise JasserLineException(lnum,'Not more than '+IntToStr(VJASS_MAX_ARRAY_INDEXES)+' is supported by vJass.');
    end else begin
        //if(arsize>JASS_ARRAY_SIZE-1) then raise JasserLineException(lnum,'Size breaks internal limits.');
        if(arsize>12000) then raise JasserLineException(lnum,'Size bigger than 12000 considered impractical.');
    end;
end;

//==============================================================================
procedure correctArray2Size(const lnum:integer; const w:integer; const h:integer; const extended:boolean=false);
 var arsize:integer;
begin
    arsize:=w*h;
    if(extended) then begin
        if(arsize>VJASS_MAX_ARRAY_INDEXES) then raise JasserLineException(lnum,'Not more than '+IntToStr(VJASS_MAX_ARRAY_INDEXES)+' elements are supported by vJass, '+IntToStr(w)+'*'+IntToStr(h)+' is '+IntToStr(arsize));
    end else begin
        if(arsize>JASS_ARRAY_SIZE-1) then raise JasserLineException(lnum,'Size breaks internal limits.');
    end;
end;

//==============================================================================
function GetLineIndexInt2(const s:string;  var ends:integer; sti:integer ):integer;
var
   i,L,o:integer;
   ts:string;
begin
    L:=Length(s);
    i:=sti;
    ends:=sti;
    while (i<=L) and (s[i]<>'[') do begin
        if( s[i]<>' ') and (s[i]<>#9) then begin
            result:=-3; exit;
        end;
        i:=i+1;
    end;
    if(i>L) then begin Result:=-3;exit;end;
    o:=i;
    i:=i+1;

    while (i<=L) and (s[i]<>']') do i:=i+1;
    if(i>L) then begin Result:=-3;exit;end;

    ends:=i+1;

    repeat
       i:=i-1;
    until (s[i]<>' ');

    repeat
       o:=o+1;
    until (s[o]<>' ');

    ts:=Copy(s,o,i-o+1);
    if (not TryStrToInt(ts,Result)) then begin
        Result:=IntegerConstants.ValueOf(ts);
    end
    else if (result<0) then Result:=-2;

end;

//==============================================================================
// A good model of correct coding would be making parsetype; call this function.
//==============================================================================
procedure addArrayType(const i: integer; const name:string; const typ:string; const arsize:integer; const arlimit:integer);
 var
    arstruct:Tstruct;
    artem:string;

begin
    SetLength(StructList,StructN+2);
    arstruct:=Tstruct.create(currentLibrary,i,false);
    arstruct.name:=name;
    StructN:=StructN+1;
    if(StructN>JASS_ARRAY_SIZE-1) then begin
        //Give me a break, 8190 classes? I am yet to see a real life serious project with such a quantity and someone would have it in a map? yeah right.
        raise JASSerLineException(i,'Outstanding, the '+IntToStr(JASS_ARRAY_SIZE-1)+' structs limit was reached! Contact vexorian');
    end;
    arstruct.customarray:=arsize;
    arstruct.customarraytype:=typ;
    arstruct.requiredspace:=arlimit;
    arstruct.maximum:=arlimit;

    StructHash.Add(name,StructN);
    StructList[StructN]:=arstruct;
    arstruct.typeid:=StructN;

    //Concatenate3(artem,'integer si__',arstruct.name,'_I=0'); addglobal(artem,i);
    //Concatenate3(artem,'integer si__',arstruct.name,'_N=0'); addglobal(artem,i);
    Concatenate3(artem,typ,' array s__',arstruct.name); addglobal(artem,i, StructN);
    if(arlimit>=JASS_ARRAY_SIZE) then begin
        GenerateExtraArrays(typ,'s__',arstruct.name,arlimit,i);
    end;

    Concatenate4(artem,'constant integer s__',arstruct.name,'_size=',IntToStr(arsize)); addglobal(artem,i, StructN);
    arstruct.addmember(i,'size',ACCESS_PUBLIC,true,false);

    arstruct.forinternaluse:=true;


    //Concatenate3(artem,'integer array si__',arstruct.name,'_V')  ; addglobal(artem,i);
    //Concatenate3(artem,'boolean array si__',arstruct.name,'_active'); addglobal(artem,i);
    //input[i]:='//processed :'+input[i];
end;    

//==============================================================================
procedure generateRequiredSizeHash;
var
    i,h,wordend,k,p:integer;
    word,tem:string;

    parents,names:array of string;
    tried: array of boolean;
    sizes: array of integer;

    n:integer;
    hash:TStringHash;

    function dfs(j:integer):integer;
        var par:string;
    begin

        if((sizes[j]=-1) and not tried[j]) then begin
            tried[j]:=true;
            par:=parents[j];
            if(par<>'') then begin
                p:=hash.valueOf(par);
                if (p>=0) and (p<n) then sizes[j]:=dfs(p);
            end;
        end;
        result:=sizes[j];
    end;

begin
  hash:=TStringHash.create;

  try
    //nextperiod:=0;
    //period:=0;

    //period:=ln div UPDATEVALUE + 1;
    //nextperiod:=period;
    SetLength(names,2);
    SetLength(sizes,2);
    SetLength(parents,2);
    SetLength(tried,2);
    n:=0;

    i:=0;
    try while(i<inputN) do begin
        GetLineWord(JHInput.Get(i),word,wordend);
        if(word='struct') or (word='interface') then begin
            if(Length(names)<=n) then begin
                SetLength(names,2*n+2);
                SetLength(parents,2*n+2);
                SetLength(sizes,2*n+2);
                SetLength(tried,2*n+2);
            end;
            GetLineToken(JHInput.Get(i),word,wordend,wordend);
            tried[n]:=false;
            names[n]:=word;
            hash.add(word,n);
            k:=GetLineIndexInt2(JHInput.Get(i),wordend,wordend);
            parents[n]:='';
            if(k>=1) then begin
                sizes[n]:=k;
            end else begin
                sizes[n]:=-1;
                if(CompareLineWord('extends',JHInput.Get(i),wordend,wordend)) then begin
                    GetLineWord(JHInput.Get(i),word,wordend,wordend);
                    parents[n]:=word;
                end;
            end;
            n:=n+1;

        end else if(word='globals') then begin
            i:=i+1;
            while(i<inputN) and (not CompareLineWord('endglobals',JHInput.Get(i),wordend) )
            do begin
               if(CompareLineWord('constant',JHInput.Get(i),wordend)
                  and CompareLineWord('integer',JHInput.Get(i),wordend,wordend)) then begin
                   GetLineToken(JHInput.Get(i),word,wordend,wordend);
                   h:=-1;
                   if (GetAssigment(JHInput.Get(i), tem, wordend)) then begin
                        GetLineToken(tem,tem,wordend);
                        if TryStrToInt(tem,h) then begin
                            if (h<0) then h:=-2;
                        end else begin
                            h:=IntegerConstants.ValueOf(tem);
                        end;
                        IntegerConstants.Add(word,h);

                    end;

               end;
               i:=i+1;
            end;


        end;
        i:=i+1;
            //if(i>=nextperiod) then begin
            //    nextperiod:=nextperiod+period;

            //end;
        //ProPosition(i/inputN);


    end;

    except
       on e:EAccessviolation do begin
           raise JasserLineDoubleException(i,'[Internal Error]',i,e.message);
       end;
    end;

    for i := 0 to n-1 do begin
        sizes[i]:=dfs(i);
        RequiredSizeHash.Add(names[i],sizes[i]);
    end;


  finally
      hash.Destroy;
  end;

end;


//==============================================================================
procedure addBigArray(const name:string; const typename:string; const size:integer; const line:integer; const width:integer = -1);
var t:integer;
begin
    if(BigArrayHash.ValueOf(name)<>-1) then begin
        raise JasserLineException(line,name+' already declared...' );
    end;
    BigArrayHash.Add(name,BigArrayN);
    if (Length(BigArrayNames)<=BigArrayN) then begin
        t:=BigArrayN+10+(BigArrayN div 5)*2;
        SetLength(BigArrayNames,t);
        SetLength(BigArrayTypes,t);
        SetLength(BigArraySizes,t);
        SetLength(BigArrayWidths,t);
        SetLength(BigArrayStructs,t);
        SetLength(BigArrayDeclLines,t);
    end;
    BigArrayNames[BigArrayN]:=name;
    BigArrayTypes[BigArrayN]:=typename;
    BigArraySizes[BigArrayN]:=size;
    BigArrayWidths[BigArrayN]:=width;
    if(width<>-1) then begin
        t:=StructN+1;
        SetLength(StructList,StructN+2);
        StructList[t]:=Tstruct.create(currentLibrary,line,false);
        StructList[t].name:=name+'[]';
        StructList[t].forInternalUse:=true;
        StructList[t].bigArrayId:=BigArrayN;
        BigArrayStructs[BigArrayN]:=t;
        StructN:=t;

    end;
    BigArrayDeclLines[BigArrayN]:=line;
    BigArrayN:=BigArrayN+1;
end;

//==============================================================================
procedure parseBigArray(var line:string; const p:integer);
var i,x,y,j:integer;
    typename,name:string;
begin
    GetLineWord(line,typename,i);
    if ((typename<>'') and CompareLineWord('array',line,i,i) ) then begin
        GetLineToken(line,name,i,i,);
        if (name='') then raise JasserLineException(p,'Expected a name.');
        if (not ValidIdentifierName(name))  then raise JasserLineException(p,'Invalid variable name: "'+name+'"');

        if(not IsWhiteSpace(line,i)) then begin
            //                     i
            // typename array name ...
            x:=GetLineIndexInt2(line,i,i);
            correctArraySize(p,x,true);
            y:=GetLineIndexInt2(line,j,i);

            if(y<-2) then begin
                // not there
                VerifyEndOfLine(line,i,p);

                line:='// processed: '+line;
                addBigArray(name,typename,x,p);

            end else begin
                line:='// processed: '+line;
                correctArraySize(p,y,true);
                correctArray2Size(p,x,y,true);
                addBigArray(name,typename,x*y,p,y);
            end;




        end;


    end;
end;

//==============================================================================
procedure GetLineIndexIntCommaInt(const s:string;  sti:integer; var endofindex:integer; var result:integer; var sresult:integer);
var
   i,L,o,j,t, comma:integer;
   ts:string;
begin
    endofindex:=0;
    L:=Length(s);
    i:=sti;
    while (i<=L) and (s[i]<>'[') do i:=i+1;
    if(i>L) then begin Result:=-1;exit;end;
    o:=i;
    i:=i+1;

    while (i<=L) and (s[i]<>']') do i:=i+1;
    if(i>L) then begin Result:=-1;exit;end;
    endofindex:=i+1;

    repeat
       i:=i-1;
    until (s[i]<>' ');

    repeat
       o:=o+1;
    until (s[o]<>' ');

    comma:=-1;
    for j := o to i do begin
        if(s[j]=',') then begin
             if(comma=-1) then comma:=j
             else begin
                 Result:=-1;
                 exit;
             end;
        end;
    end;


    if(comma=-1) then begin
        ts:=Copy(s,o,i-o+1);
        if (not TryStrToInt(ts,Result)) then begin
            Result:=IntegerConstants.ValueOf(ts);
        end
        else if (result<0) then Result:=-2;
        sresult:=-1;
    end else begin
        t:=comma;
        repeat
            t:= t-1;
        until (s[t]<>' ');

        ts:=Copy(s,o,t-o+1);
        if (not TryStrToInt(ts,Result)) then begin
            Result:=IntegerConstants.ValueOf(ts);
        end
        else if (result<0) then Result:=-2;

        if(result>=0) then begin
            t:=comma;
            repeat
                t:=t+1
            until (s[t]<>' ');
            ts:=Copy(s,t,i-t+1);
            if (not TryStrToInt(ts,sResult)) then begin
                sResult:=IntegerConstants.ValueOf(ts);
            end
            else if (sresult<0) then sResult:=-2;
        end;


    end;

end;

//==========================================================================
procedure parsetype(const i: integer; const word:string; var wordend:integer; var memb:Tmember);
var
    typename:string;
    arraytype:string;
    arsize,arlimit:integer;

    tmstruct:Tstruct;
    tem:string;
begin
    typename:=word;
    GetLineWord(JHInput.Get(i),typename,wordend,wordend);
    if(typename='') then raise JASSerLineException(i,'Expected an struct name');
    if (not validIdentifierName(typename)) then raise JASSerLineException(i,'Invalid name: '+typename);

    VerifyRedeclarationRaise(i,typename);
    // GetLineWord(JHInput.Get(i),word,wordend,wordend);
    if not CompareLineWord('extends',JHInput.Get(i),wordend,wordend)
       then raise JasserLineException(i,'Expected extends');
    GetLineWord(JHInput.Get(i),arraytype,wordend,wordend);
    if(arraytype='') then raise JASSerLineException(i,'Expected a name');
    if (not validIdentifierName(arraytype)) then raise JASSerLineException(i,'Invalid name: '+arraytype);
    if CompareLineToken('array',JHInput.Get(i),wordend,wordend) then begin
        //action!
        SetLength(StructList,StructN+2);
        tmstruct:=Tstruct.create(currentLibrary,i,false);
        tmstruct.name:=typename;
        StructN:=StructN+1;
        if(StructN>JASS_ARRAY_SIZE-1) then begin
            //Give me a break, 8190 classes? I am yet to see a real life serious project with such a quantity and someone would have it in a map? yeah right.
            raise JASSerLineException(i,'Outstanding, the '+IntToStr(JASS_ARRAY_SIZE-1)+' structs limit was reached! Contact vexorian');
        end;
        StructHash.Add(typename,StructN);
        StructList[StructN]:=tmstruct;
        tmstruct.typeid:=StructN;
        tmstruct.customarraytype:=arraytype;
        // '    [    ]';

        GetLineIndexIntCommaInt(JHInput.Get(i),wordend,wordend,arsize,arlimit);
        correctArraySize(i,arsize);
        VerifyEndOfLine(JHInput.Get(i),wordend,i);

        if(arlimit>=0) then begin

            if(arlimit>VJASS_MAX_ARRAY_INDEXES) then begin
                raise JasserLineException(i,'Jass array space used by a single dynamic array is capped to '+IntToStr(VJASS_MAX_ARRAY_INDEXES));
            end;
            tmstruct.requiredspace:=arlimit;
            tmstruct.maximum:=arlimit;

            if (arsize>arlimit div 8) then begin
              raise JasserLineException(i,'Not enough storage space for more than 8 instances, considered impractical, array size='+IntToStr(arsize)+' , storage limit:'+IntToStr(arlimit));
            end;
        end else if (arsize>JASS_ARRAY_SIZE div 8) then begin
            raise JasserLineException(i,'Not enough storage space for more than 8 instances, considered impractical, array size='+IntToStr(arsize)+' , storage limit:'+IntToStr(JASS_ARRAY_SIZE));
        end;
        tmstruct.customarray:=arsize;
        tmstruct.addmember(-1,'create',ACCESS_PUBLIC,true,true).construct:=true;
        memb:=tmstruct.addmember(-1,'destroy',ACCESS_PUBLIC,false,true);
        memb.destruct:=true;


        //Done parsing Cool, isn't it?
            Concatenate3(tem,'integer si__',tmstruct.name,'_I=0'); addglobal(tem,i, tmstruct.typeid);
            Concatenate3(tem,'integer si__',tmstruct.name,'_F=0'); addglobal(tem,i, tmstruct.typeid);
            Concatenate3(tem,arraytype,' array s__',tmstruct.name); addglobal(tem,i, tmstruct.typeid);
         generateExtraArrays(arraytype,'s__',tmstruct.name,arlimit,i);

        Concatenate4(tem,'constant integer s__',tmstruct.name,'_size=',IntToStr(arsize)); addglobal(tem,i, tmstruct.typeid);
        memb:=tmstruct.addmember(i,'size',ACCESS_PUBLIC,true,false);
        Concatenate3(tem,'integer array si__',tmstruct.name,'_V')  ; addglobal(tem,i, tmstruct.typeid);
        generateExtraArrays('integer',RConcatenate3('si__',tmstruct.name,'_') ,'V',arlimit,i);

        JHInput.Prepend('//processed :', i);

    end;

end;

//==============================================================================
procedure GetStaticMethod(const structname:string; const methodname:string; const decl:integer; out struct:Tstruct; out memb:Tmember);
var
   x:integer;
begin
   x:=StructHash.ValueOf(structname);
   if(x=-1) then
       raise JasserLineException(decl, 'Cannot find struct: '+structname);

   struct:=StructList[x];
   if(not struct.getMember(methodname,memb) ) then
       raise JasserLineDoubleException(decl, 'Cannot find member: '+methodname, struct.decl,'---- In this struct declaration');
   if( not(memb.isstatic) or not(memb.ismethod) ) then
          raise JasserLineDoubleException(decl, 'Expected a static method.', memb.decl,'---- '+memb.name+' is not a static method.');
end;

//==============================================================================
procedure EvaluateHook(const s:string; const decl:integer);
var
 nativename, structname, funcname:string;
 func:TJassFunc;
 x:integer;
 memb:Tmember;
 struct:Tstruct;
 hook:Thook;

    function dotcheck(const name:string; var first:string; var second:string):boolean;
     var
        i:integer;
    begin
        Result:=false;
        for i := 1 to Length(name) do
            if(name[i]='.') then begin
                Result:=true;
                first := Copy(name,1,i-1);
                second := Copy(name,i+1, Length(name)-i);
            end;


    end;

begin
    CompareLineWord('hook',s,x);
    GetLineWord(s,nativename, x,x);
    if( not ValidIdentifierName(nativename) ) then
        raise JasserLineException(decl,'Syntax error');

    GetLineWord(s,funcname, x,x);
    VerifyEndOfLine(s, x, decl);

    //does the native exist??!
    func := GetJassFuncDefinition(nativename);
    if( func = nil ) then begin
        raise JasserLineException(decl,'Unable to find native: '+nativename);
    end;

    hook:= Thook.Create;
    if dotCheck(funcname, structname, funcname) then begin
        if( not ValidIdentifierName(funcname) or not(ValidIdentifierName(structname))  ) then
            raise JasserLineException(decl,'Syntax error');
        GetStaticMethod(structname,funcname, decl, struct, memb );
        memb.abuse:=true;
        hook.isMethod:=true;
        hook.memb:=memb;
        hook.struct:=struct;
    end else begin
        structname:='';
        if not ValidIdentifierName(funcname) then
            raise JasserLineException(decl,'Syntax error');
        x := FunctionHash.valueOf(funcname);
        if(x=-1) then
            raise JasserLineException(decl,'Unable to find function : '+funcname);
        FunctionData[x].abuse:=true;
        prototype[FunctionData[x].prototypeid ].abuse:=true;

        hook.isMethod:=false;
        hook.funcid:= x;
        FunctionDataUsed:=true;
    end;
    x:= HookedNativeHash.ValueOf(nativename);
    if(x=-1) then begin
        HookedNatives.Add(THookedNative.create);
        x:= HookedNatives.Count - 1;
        THookedNative(HookedNatives[x]).nativename:=nativename;
        THookedNative(HookedNatives[x]).hooks:= TList.create;
        HookedNativeHash.Add(nativename, x);
    end;
    THookedNative(HookedNatives[x]).hooks.add(hook);
end;




//==============================================================================
//  Struct parsing
//==============================================================================
procedure Step00(var nativesblock: string);
var
    i,j,k,h,siz,wordend:integer;
    membbigarr,membbigarr2:integer;
    indent:integer;
    priv:integer;
    reqsize:integer;
    stat:boolean;
    stub:boolean;
    deleg:boolean;
    arr:boolean;
    consta:boolean;
    propertyoperator:boolean;
    interfa:boolean;
    memb,memb2:Tmember;
    tmstruct:TStruct;
    tem,tem2:string;
    init,ind,idn:string;
    typen:string;
    word:string;
    
begin
    currentLibrary := '';

    //step 1, before anything else parse interfaces and parent structs for [] (max index space operator)
    generateRequiredSizeHash;

    i:=0;

    //step 1.2 Parse the structs themselves and generate globals, replace methods, etc.
    try while(i<inputN) do begin
        //ProPosition(i/inputN);


//        WriteLn(DEBUGFILE,JHInput.Get(i));
        GetLineWord(JHInput.Get(i),word,wordend);
        interfa:=(word='interface');
        if( word='struct') or (interfa) then begin
            GetLineToken(JHInput.Get(i),word,wordend,wordend);
            if(word='') then raise JASSerLineException(i,'Expected an struct name');

            if (not validIdentifierName(word)) then begin
                raise JASSerLineException(i,'Invalid identifier name: '+word);
            end;
            VerifyRedeclarationRaise(i,word);

            SetLength(StructList,StructN+2);
            tmstruct:=Tstruct.create(currentLibrary,i,interfa);
            StructN:=StructN+1;
            if(StructN>JASS_ARRAY_SIZE-1) then begin
                //Give me a break, 8190 classes? I am yet to see a real life serious project with such a quantity and someone would have it in a map? yeah right.
                raise JASSerLineException(i,'Outstanding, the '+IntToStr(JASS_ARRAY_SIZE-1)+' structs limit was reached! Contact vexorian');
            end;
            StructHash.Add(word,StructN);
            StructList[StructN]:=tmstruct;
            tmstruct.typeid:=StructN;


            tmstruct.name:=word;

            reqsize:=GetLineIndexInt2(JHInput.Get(i),j,wordend);
            if(reqsize<>-3) and (reqsize<0) then raise JasserLineException(i,'Invalid max indexes specifier');
            if(reqsize>=0) then
               wordend:=j;
            GetLineWord(JHInput.Get(i),word, j, wordend);


            if(word='extends') then begin

                if(interfa) then raise JASSerLineException(i,'Interfaces can''t extend');
                if(reqsize>=0) then raise JasserLineException(i,'Cannot use extends on an struct that specifies max indexes');
                GetLineWord(JHInput.Get(i),word,wordend,j);

                if(word='array') then begin
                    tmstruct.makeArrayStruct;
                    if(not IsWhiteSpace(JHInput.Get(i),wordend)) then begin
                        reqsize:=GetLineIndexInt2(JHInput.Get(i),wordend,wordend);
                        CorrectArraySize(i,reqsize);
                    end;


                end else begin

                   tmstruct.parentname:=word;
                   tmstruct.parent:=0;
                   reqsize:=RequiredSizeHash.ValueOf(word);

                end;
            end else if(word<>'') then begin
                JasserLineException(i,'Unexpected: '+word);
            end;
            if(reqsize>=0) then begin
                tmstruct.requiredspace:=reqsize;
                tmstruct.maximum:=reqsize;
            end else reqsize:=JASS_ARRAY_SIZE-1;

            VerifyEndOfLine(JHInput.Get(i),wordend,i);

            { integer si_type_I=0
              integer si_type_N=0
              integer array si_type_V=0
            }
            Concatenate4(tem,'constant integer si__',tmstruct.name,'=',IntToStr(tmstruct.typeid)); addglobal(tem,i, tmstruct.typeid);
            if( not tmstruct.isarraystruct) then begin

                if(tmstruct.parent=-1) then begin
                    Concatenate3(tem,'integer si__',tmstruct.name,'_F=0 //MOOOO'); addglobal(tem,i, tmstruct.typeid);
                    Concatenate3(tem,'integer si__',tmstruct.name,'_I=0'); addglobal(tem,i, tmstruct.typeid);
                    Concatenate3(tem,'integer array si__',tmstruct.name,'_V')  ; addglobal(tem,i, tmstruct.typeid);
                    generateExtraArrays('integer',RConcatenate3('si__',tmstruct.name,'_'),'V',reqsize,i);
                end;
            end;

            if(interfa) then begin
                JHInput.Rewrite(i, '//! ignore');
                Concatenate3(tem,'integer array si__',tmstruct.name,'_type')  ; addglobal(tem,i, tmstruct.typeid);
                generateExtraArrays('integer',RConcatenate3('si__',tmstruct.name,'_'),'type',reqsize,i);
                Concatenate3(tem,'trigger array st__',tmstruct.name,'_onDestroy')  ; addglobal(tem,i, tmstruct.typeid);
            end;



            i:=i+1;
            while(i<inputN) do begin
              GetLineWord(JHInput.Get(i),word,wordend);
              indent:=wordend-Length(word)-1;
              if(word='') or ((Length(word)>=2) and (word[1]='/') and (word[2]='/')) then begin
                  if(word='//!') then begin
                      if CompareLineWord('ModuleOnInit',JHInput.Get(i),k,wordend)  then
                      begin
                           GetLineWord(JHInput.Get(i), word, wordend,k);
                           tmstruct.addModuleOnInit(word);
                      end;
                      k:=wordend;
                      if CompareLineWord('pragma',JHInput.Get(i),k,k)
                        and CompareLineWord('implicitthis',JHInput.Get(i),k,k)
                      then
                      begin
                          tmstruct.zincstruct:=true;
                      end;
                  end;

              end else begin
                //membbigarr:=-1;
                //membbigarr2:=-1;
                if (word='endstruct') then begin
                    if(interfa) then raise JASSerLineException(i,'Unexpected endstruct');
                    break;
                end;
                if (word='endinterface') then begin
                    if(not interfa) then raise JASSerLineException(i,'Unexpected endinterface');
                    JHInput.Rewrite(i, '//! ignore');
                    break;
                end;

                if(word='struct') or (word='interface') then raise JASSerLineDoubleException(i,'Nested struct declarations are not allowed.',tmstruct.decl,'Inside this block.');
                priv:=ACCESS_PUBLIC;
                if(word='public') then GetLineWord(JHInput.Get(i),word,wordend,wordend)
                else if (word='private') then begin
                    GetLineWord(JHInput.Get(i),word,wordend,wordend);
                    priv:=ACCESS_PRIVATE;
                end else if(word='readonly') then begin
                    priv:=ACCESS_READONLY;
                    GetLineWord(JHInput.Get(i),word,wordend,wordend);
                end;

                stat:=(word='static');
                if stat then begin
                     GetLineWord(JHInput.Get(i),word,wordend,wordend);
                end;
                stub:=(word='stub');
                if stub then begin
                     GetLineWord(JHInput.Get(i),word,wordend,wordend);
                end;

                deleg:=(word='delegate');
                if deleg then begin
                     GetLineWord(JHInput.Get(i),word,wordend,wordend);
                end;


                // public/private static constant
                consta:=(word='constant');
                if consta then begin
                     GetLineWord(JHInput.Get(i),word,wordend,wordend);
                end;

                if(word='constant') or (word='static') or (word='private') or (word='public')  or (word='stub') then
                    raise JASSerLineException(i,'Wrong keyword order (valid is : [public/private] [static/stub] [constant] <type/method> ...)');

                if(word='function') then raise JasserLineException(i,'Unexpected: function');
                if(word='method') then begin

                    if(priv=ACCESS_READONLY) then raise JASSerLineException(i,'Methods cannot be readonly');
                    //A method, omg.
                    if(consta and not stat) then raise JASSerLineException(i,'A constant instance method?');
                    if(deleg) then raise JASSerLineException(i,'Only variable members (not method) can be delegates.');

                    tem:='';



                    GetLineWord(JHInput.Get(i),idn,wordend,wordend);
                    //word holds the name?

                    if(idn='') then raise JASSerLineException(i,'Expected a name');

                    if( interfa and stat ) then begin
                         if (idn<>'create') then
                            raise JASSerLineException(i,'Expected: create');
                         if( not CompareLineWord('takes',JHInput.Get(i),wordend,wordend))  then
                             raise JASSerLineException(i,'Expected: "takes nothing"');
                         if( not CompareLineWord('nothing',JHInput.Get(i),wordend,wordend))  then
                             raise JASSerLineException(i,'Expected: "takes nothing"');

                         VerifyEndOfLine(JHInput.Get(i),wordend,i);

                         tmstruct.noargumentcreate:=true;
                         JHInput.Rewrite(i, '//! ignore');
                         i:=i+1;
                         continue;
                    end;

                    propertyoperator:=false;
                    if (CompareSubString(idn,1,8,'operator') and ( (Length(idn)=8) or not(idn[9] in IDENTIFCHARS) )  ) then begin
                        GetLineWord(JHInput.Get(i),idn,wordend,wordend-Length(idn)+8);

                        if(ValidIdentifierName(idn)) then begin
                            propertyoperator:=true;
                            h:=tmstruct.membershash.ValueOf(idn);
                            if(h<>-1) then raise JASSerLineException(i,'Member redeclared : '+idn);
                            idn:='_get_'+idn;
                        end else if( Length(idn)>=2) and (idn<>'[]=') and (idn[Length(idn)]='=') and(idn[Length(idn)-1]<>'=') then begin
                            propertyoperator:=true;
                            idn:=Copy(idn,1,Length(idn)-1);
                            if (not ValidIdentifierName(idn)) then raise JasserLineException(i,'Not a valid identifier name for custom assign operator');
                            h:=tmstruct.membershash.ValueOf(idn);
                            if(h<>-1) then raise JASSerLineException(i,'Member redeclared : '+idn);
                            idn:='_set_'+idn;

                        end else if ((idn<>'[]') and (idn<>'[]=') and (idn<>'<') and (idn<>'==') ) then begin
                            raise JasserLineException(i,'Expected "[]","[]=","<","==" or an identifier name');
                        end;

                    end;


                    if not(ValidIdentifierName(idn)) and not propertyoperator then begin

                        if (idn='<') then begin
                            //if (interfa) then raise JASSerLineException(i,'Operator < not supported as interface method yet.');
                            idn:='_lessthan';
                        end
                        else if (idn='[]') then idn:='_getindex'
                        else if (idn='[]=') then idn:='_setindex'
                        else if (idn='==') then idn:='_equalto'
                        else
                            raise JASSerLineException(i,'Not a valid identifier name');
                    end;


                    if ((idn[1]='_') and stat) then begin
                        if(idn='_getindex') then idn:='_staticgetindex'
                        else if(idn='_setindex') then idn:='_staticsetindex'
                        else if( (idn='_lessthan') or (idn='_equalto') ) then raise JasserLineException(i,'< and == are not supported for static operators.');

                    end;

                    h:=tmstruct.membershash.ValueOf(idn);
                    if(h<>-1) then raise JASSerLineException(i,'Member redeclared : '+idn);


                    memb:=tmstruct.addmember(i, idn, priv ,stat,true);

                    if(stub) then begin
                        memb.stub:=true;
                        tmstruct.gotStubMethods:=true;
                        memb.abuse:=true;
                    end;

                    if(idn='onDestroy') then begin
                        if interfa then raise JASSerLineException(i,'Don''t declare onDestroy for an interface');
                        if tmstruct.isarraystruct then raise JASSerLineException(i,'Don''t declare onDestroy for an array struct');

                        tmstruct.ondestroy:=memb;
                        if(tmstruct.parent<>-1) then memb.fromparent:=true;
                        memb.abuse:=true;
                    end;

                    if(idn='onInit') then begin
                        if interfa then raise JASSerLineException(i,'Don''t declare onInit for an interface');
                        if not stat then raise JASSerLineException(i,'onInit must be static');

                        if(tmstruct.parent<>-1) then memb.fromparent:=true;

                    end;


                    if(interfa) then memb.abuse:=true;

                        ind:='';
                        while(indent>0) do begin
                            Swrite(ind,' ');
                            indent:=indent-1;
                        end;
                        if(consta) then
                            Concatenate7(tem,ind,'constant function ','s__',tmstruct.name,'_',idn,' takes ')
                        else
                            Concatenate7(tem,ind,'function ','s__',tmstruct.name,'_',idn,' takes ');

                    //IF it is not static then we have to add 'takes integer this'
                    //method boo takes type name returns something
                    //method boo takes type1 name1, type1 name2 returns something
                    //method boo takes nothing returns something

                    if(not stat) then begin
                        SWrite(tem,tmstruct.name);
                        Swrite(tem,' this');
                        GetLineWord(JHInput.Get(i),word,wordend,wordend);

                      if (interfa and (memb.name='_lessthan')) then begin
                          if (word<>'') then raise JasserLineException(i,'Expected end of line (interface operator < does not need a complete declaration)');
                          memb.returntype:='boolean';
                          memb.addarg(tmstruct.name,'dummy');
                      end else begin
                        if(word<>'takes') then raise JASSerLineException(i,'Expected "takes"');
                        GetLineWordAlsoComma(JHInput.Get(i),typen,wordend,wordend);
                        if(typen='nothing') then begin
                            Swrite(tem,Copy(JHInput.Get(i),wordend,Length(JHInput.Get(i))));
                                GetLineWordAlsoComma(JHInput.Get(i),typen,wordend,wordend);
                                if(typen='returns') then begin
                                    GetLineWord(JHInput.Get(i),memb.returntype,wordend,wordend);
                                end else raise JASSerLineException(i,'Expected returns');

                        end else begin
                            if(tmstruct.ondestroy=memb) then raise JASSerLineException(i,'Wrong onDestroy definition');
                            ind:=tem;
                            Concatenate4(tem,ind,',',typen,Copy(JHInput.Get(i),wordend,Length(JHInput.Get(i))));

                            while(wordend<Length(JHInput.Get(i)))
                            do begin
                                //read name.
                                GetLineWordAlsoComma(JHInput.Get(i),word,wordend,wordend);

                                memb.addarg(typen,word);

                                //read type or returns.
                                GetLineWordAlsoComma(JHInput.Get(i),typen,wordend,wordend);
                                if(typen='returns') then begin
                                    GetLineWord(JHInput.Get(i),memb.returntype,wordend,wordend);
                                    break;
                                end;
                                //repeat

                            end;
                        end;
                      end;


                    end else begin
                        if(tmstruct.ondestroy=memb) then raise JASSerLineException(i,'onDestroy must be an instance method.');
                        if(interfa) then raise JASSerLineException(i,'Interfaces cannot have static methods');
                        if(not comparelineWord('takes',JHInput.Get(i),wordend,wordend)) then raise JASSerLineException(i,'Expected "takes"');
                        Swrite(tem,Copy(JHInput.Get(i),wordend,Length(JHInput.Get(i))));
                        GetLineWord(JHInput.Get(i),typen,wordend,wordend);
                        if(typen<>'nothing') then begin
                            if(memb.name='onInit') then raise JasserLineException(i,'onInit must have no argument list');

                            while(wordend<Length(JHInput.Get(i)))
                            do begin
                                //read name.
                                GetLineWordAlsoComma(JHInput.Get(i),word,wordend,wordend);
                                memb.addarg(typen,word);

                                //read type or returns.
                                GetLineWordAlsoComma(JHInput.Get(i),typen,wordend,wordend);
                                if(typen='returns') then begin
                                    GetLineWord(JHInput.Get(i),memb.returntype,wordend,wordend);
                                    break;
                                end;

                                //repeat
                            end;
                        end else begin
                            GetLineWordAlsoComma(JHInput.Get(i),typen,wordend,wordend);
                            if(typen='returns') then begin
                                GetLineWord(JHInput.Get(i),memb.returntype,wordend,wordend);
                            end else raise JASSerLineException(i,'Expected returns');
                        end;


                    end;

                    if (CompareLineWord('defaults',JHInput.Get(i),wordend,wordend)) then begin
                         if (not interfa) then raise JasserLineException(i,'defaults is only compatible to interface methods');
                         GetLineWord(JHInput.Get(i),word,wordend,wordend);
                         if (word='') then raise JasserLineException(i,'Expected default value or nothing');
                         memb.interdefault:=word;

                         if(( word='nothing') and (memb.returntype<>'nothing')) then raise JasserLineException(i,'Cannot default nothing, method returns '+memb.returntype);
                         if(( word<>'nothing') and (memb.returntype='nothing')) then raise JasserLineException(i,'Only possible default is nothing since method returns nothing');
                    end;


                    //must be strict on operator declarations
                    if (memb.name='_getindex') or (memb.name='_staticgetindex') then begin
                        if (memb.returntype='nothing') then raise JasserLineException(i,'[] operator must have return a value');


                        if (memb.argnumber<>1) then  raise JasserLineException(i,'operator [] requires 1 argument.');

                        if (memb.argnumber<>1) then  raise JasserLineException(i,'operator [] requires 1 argument.');
                    end else if (memb.name='_setindex') or (memb.name='_staticsetindex') then begin
                        if (memb.argnumber<>2) then  raise JasserLineException(i,'operator []= requires 2 arguments.');
                    end else if (memb.name='_lessthan') then begin
                        if ((memb.argnumber<>1) or (memb.argtypes[0]<>tmstruct.name)  )then  raise JasserLineException(i,' operator < requires 1 argument of type: '+tmstruct.name);
                        if (memb.returntype<>'boolean') then  raise JasserLineException(i,'< operator must return a boolean value');
                    end else if (memb.name='_equalto') then begin
                        if ((memb.argnumber<>1) or (memb.argtypes[0]<>tmstruct.name)  )then  raise JasserLineException(i,' operator == requires 1 argument of type: '+tmstruct.name);
                        if (memb.returntype<>'boolean') then  raise JasserLineException(i,'== operator must return a boolean value');
                    end else if( propertyoperator and (Copy(memb.name,1,5) = '_get_') ) then begin
                        if (memb.argnumber<>0) then  raise JasserLineException(i,'Property operator must take nothing.');
                        if( memb.returntype='nothing') then raise JasserLineException(i,'Property operator must have a return type.');
                    end else if( propertyoperator and (Copy(memb.name,1,5) = '_set_') ) then begin
                        if (memb.argnumber<>1) then  raise JasserLineException(i,'Property assignment operator must have exactly one argument.');
                    end else if(memb.name='create') then begin
                        if(not memb.isstatic) then  raise JasserLineException(i,'method create must be static');

                        if( memb.returntype<>tmstruct.name) then raise JasserLineException(i,'method create must return '+tmstruct.name);
                        tmstruct.customcreate:=true;
                    end else if(memb.name='destroy') then begin
                        if( memb.isstatic) then  raise JasserLineException(i,'method destroy must not be static');

                        if( memb.returntype<>'nothing') then raise JasserLineException(i,'method destroy must return nothing');
                        if( memb.argnumber <> 0) then raise JasserLineException(i,'method destroy must have 0 arguments');

                    end;

                    if(tmstruct.ondestroy=memb) and(memb.returntype<>'nothing') then raise JASSerLineException(i,'onDestroy must return nothing');

                    if(interfa) then begin
                        Concatenate4(tem,'trigger array st__',tmstruct.name,'_',memb.name)  ; addglobal(tem,i, tmstruct.typeid);
                        JHInput.Rewrite(i, '//! ignore')
                    end else begin
                        //skip to endmethod
                        JHInput.Rewrite(i, tem);
                        h:=i;
                        //skip to endmethod
                        repeat
                            i:=i+1;
                            if(i=inputN) then JASSerLineException(h,'Missing "endmethod"');
                            GetLineWord(JHInput.Get(i),word,wordend);
                            if((word='endfunction') or (word='function') or (word='method')) then raise JASSerLineException(i,'Unexpected "'+word+'"');
                            if(word='endmethod') then break;
                            if(word='endstruct') then raise JASSerLineException(h,'Missing "endmethod"');
                        until false;

                        if(tmstruct.ondestroy=memb) then begin
                            tmstruct.members[tmstruct.membershash.valueOf('deallocate')].decl:=i;
                        end;
                        tem:='';
                        indent:=wordend-10; //'endmethod'
                        while(indent>0) do begin
                            Swrite(tem,' ');
                            indent:=indent-1;
                        end;
                        Swrite(tem,'endfunction');
                        Swrite(tem,Copy(JHInput.Get(i),wordend,Length(JHInput.Get(i))));
                        JHInput.Rewrite(i, tem);
                    end;


                end else begin
                    //word holds a type
                    typen:=word;
                    GetLineToken(JHInput.Get(i),idn,wordend,wordend);
                    arr:=(idn='array');
                    if(arr and tmstruct.isarraystruct and not stat) then
                        raise JASSerLineException(i,'Array structs cannot have array members yet, use a dynamic array instead, if necessary.');

                    membbigarr:=-1;
                    membbigarr2:=-1;
                    if(arr) then begin
                        GetLineToken(JHInput.Get(i),idn,wordend,wordend);
                    end;
                    if ( FindOddCharacters(JHInput.Get(i),wordend-1) ) then
                        raise JasserLineException(i, 'Syntax Error');

                    if(idn='') then raise JASSerLineException(i,'Expected a name');

                    if GetAssigment(JHInput.Get(i),init,wordend) then begin
                       if(init='') then raise JASSerLineException(i,'Expected: default value after =');
                    end else init:='';
                    if(init<>'') and not(stat) and tmstruct.isArrayStruct then
                        raise JASSerLineException(i,'Array structs cannot have default values.');

                    h:=tmstruct.membershash.ValueOf(idn);
                    if(h<>-1) then raise JASSerLineException(i,'Member redeclared : '+idn);
                    h:=tmstruct.membershash.ValueOf('_get_'+idn);
                    if(h<>-1) then raise JASSerLineException(i,'Member name already in use by an operator: '+idn);
                    h:=tmstruct.membershash.ValueOf('_set_'+idn);
                    if(h<>-1) then raise JASSerLineException(i,'Member name already in use by an operator: '+idn);




                    siz:=0;
                    if(stat) then begin
                        if(arr) then begin
                            if(consta) then raise JASSerLineException(i,'constant arrays are not supported');
                            if(init<>'') then raise JASSerLineException(i,'Unable to initialize an array.');

                            if(not IsWhiteSpace(JHInput.Get(i),wordend)) then begin
                                membbigarr:=GetLineIndexInt2(JHInput.Get(i),wordend,wordend);
                                correctArraySize(i,membbigarr,true);
                                membbigarr2:=GetLineIndexInt2(JHInput.Get(i),k,wordend);
                                if(membbigarr2=-3) then membbigarr2:=-1
                                else begin
                                    wordend:=k;
                                    correctArraySize(i,membbigarr2,true);
                                    correctArraySize(i,membbigarr*membbigarr2,true);
                                end;
                                VerifyEndOfLine(JHInput.Get(i),wordend,i);
                            end;


                        end;

                        if (consta and (init='')) then raise JASSerLineException(i,'A constant requires initializing.');

                        if (consta and (typen='integer')) then begin


                           GetLineToken(init,word,k);
                           k:=-1;
                           if TryStrToInt(word,k) then begin
                               if (k<0) then k:=-2;
                           end else begin
                               k:=IntegerConstants.ValueOf(word);
                           end;
                           Concatenate3(tem,tmstruct.name,'.',idn);
                           IntegerConstants.Add(tem,k);
                           IntegerConstants.Add('.'+idn,k);
                        end;

                    end else begin
                        if(consta) then raise JASSerLineException(i,'constant instance members are not supported (Did you want an static variable instead?)');


                        //if(arr) then raise JASSerLineException(i,'array instance variables are not supported');
                        if(arr) then begin
                            tmstruct.containsarraymembers:=true;

                            if(init<>'') then raise JASSerLineException(i,'Unable to initialize an array.');
                            concatenate4(tem,'_',tmstruct.name,'_',idn);
                            siz:=GetLineIndexInt2(JHInput.Get(i),wordend,wordend);
                            correctArraySize(i,siz);
                            VerifyEndOfLine(JHInput.Get(i),wordend,i);

                            addArrayType(i, tem,typen,siz, tmstruct.requiredspace);
                            typen:=tem;

                            if(tmstruct.parent<>-1)then
                                Concatenate7(tem,'    set s__',tmstruct.name,'_',idn,'[this]=(kthis-1)*',IntToStr(siz),#13#10)
                            else begin
                                if(tmstruct.requiredspace>=JASS_ARRAY_SIZE) then begin
                                    tem:='';
                                    GenerateMultiArrayPicker(RConcatenate3('s__',tmstruct.name,'_'),idn,tmstruct.requiredspace,'this',4,'set ','=(this-1)*'+IntToStr(siz),tem);
                                end else
                                    Concatenate7(tem,'    set s__',tmstruct.name,'_',idn,'[this]=(this-1)*',IntToStr(siz),#13#10);
                            end;
                            swrite(tmstruct.oninitv,tem); //let's use oninitv here


                        end;
                    end;
                    if(init='') then  VerifyEndOfLine(JHInput.Get(i), wordend,i);



                    if(stat) then begin
                        if(arr) then
                            concatenate5(tem,typen,' array s__',tmstruct.name,'_',idn)
                        else if(consta) then
                            concatenate8(tem,'constant ',typen,' s__',tmstruct.name,'_',idn,'=',init)
                        else if(init<>'') then
                            concatenate7(tem,typen,' s__',tmstruct.name,'_',idn,'=',init)
                        else
                            concatenate5(tem,typen,' s__',tmstruct.name,'_',idn);
                    end else begin
                        concatenate5(tem,typen,' array s__',tmstruct.name,'_',idn);
                        generateExtraArrays(typen,RConcatenate3('s__',tmstruct.name,'_'),idn,reqsize,i);
                    end;
                    if(membbigarr>-1) then begin
                        concatenate4(tem,'s__',tmstruct.name,'_',idn);
                        if(membbigarr2>-1) then begin
                            addBigArray(tem,typen,membbigarr*membbigarr2,i, membbigarr2);
                        end else begin
                            addBigArray(tem,typen,membbigarr,i);
                        end;
                    end else begin
                        addglobal(tem,i, tmstruct.typeid);
                    end;

                    memb:=tmstruct.addmember(i, idn, priv,stat,false);
                    if(deleg) then tmstruct.addDelegate(memb);
                    memb.arraydummy :=(siz);


                    if(init<>'') and not(stat)  then begin
                        //   set s__structname_membername=inivalue
                        memb.oninit_value:=init;
                        memb.oninit_struct:=tmstruct.name;
                    end;


                    memb.returntype:=typen;

                    if(siz<>0) then begin
                        k:=(tmstruct.requiredspace) div siz-1;
                        if (tmstruct.maximum>k) then tmstruct.maximum:=k;

                        if( (not tmstruct.addedArrayControl) and (tmstruct.parent<>-1)) then begin
                           Concatenate3(tem,'integer si__',tmstruct.name,'_arrI=0'); addglobal(tem,i, tmstruct.typeid);
                           Concatenate3(tem,'integer si__',tmstruct.name,'_arrN=0'); addglobal(tem,i, tmstruct.typeid);
                           Concatenate3(tem,'integer array si__',tmstruct.name,'_arr'); addglobal(tem,i, tmstruct.typeid);
                           if(tmstruct.requiredspace>=JASS_ARRAY_SIZE) then begin
                               GenerateExtraArrays('integer',RConcatenate3('si__',tmstruct.name,'_'),'arr',tmstruct.requiredspace,i);
                           end;
                           Concatenate3(tem,'integer array si__',tmstruct.name,'_arrV')  ; addglobal(tem,i, tmstruct.typeid);
                           if(tmstruct.requiredspace>=JASS_ARRAY_SIZE) then begin
                               GenerateExtraArrays('integer',RConcatenate3('si__',tmstruct.name,'_'),'arrV',tmstruct.requiredspace,i);
                           end;
                           tmstruct.addedArrayControl:=true;
                        end;
                    end;



                    if(arr and stat) then memb.isstaticarray:=true;

                    JHInput.Rewrite(i, '//! ignore');
                end;

              end;
                i:=i+1;
            end;

            if(tmstruct.membershash.valueof('create')=-1) and not(tmstruct.isArrayStruct) then begin
                memb:=tmstruct.addmember(-1,'create',ACCESS_PUBLIC,true,true);
                memb.construct:=true;
                memb.access:=ACCESS_PUBLIC;
            end;

            if(tmstruct.membershash.valueof('destroy')=-1) and not(tmstruct.isArrayStruct) then begin
                memb:=tmstruct.addmember(-1,'destroy',ACCESS_PUBLIC,false,true);
                memb.destruct:=true;
                memb.access:=ACCESS_PUBLIC;
                tmstruct.getmember('deallocate',memb2);
                if(memb2 <> nil ) then
                     memb.decl:=memb2.decl
                else
                    memb.decl := 0;

            end;


//            if(input[DEBUGID][1]<>DEBUGSTR) then raise JASSerLineException(tmstruct.decl,'Access '+IntToStr(StructN));
            tmstruct.endline:=i;
            if(i=inputN) then raise JASSerLineException(tmstruct.decl,'Missing endstruct');


        end
        // good thing we saved library and struct borders
        else if word = '//!' then begin
                GetLineWord(JHInput.Get(i),word,wordend, wordend);
                if (word = 'library') or (word = 'scope') then begin
                    GetLineWord(JHInput.Get(i),word,wordend, wordend);
                    currentLibrary := word;
                end else if (word = 'endlibrary') or (word = 'endscope') then begin
                    currentLibrary := '';
                end;
             end
        else if(word='hook') then begin
            hookLines.add(Pointer(i));
        end else if (word='type') then begin
            parsetype(i, word, wordend, memb);
        end else if (word='constant') then begin
              GetLineWord(JHInput.Get(i),word,wordend, wordend);
              if( word='function') then
                   functionLines.add(Pointer(i) )
              else if(word='native') then
                   nativeLines.add(Pointer(i));


        end else if(word='function') then begin
              functionLines.add(Pointer(i) );
        end else if (word='native') then begin
              nativeLines.add(Pointer(i));
        end else if (word='globals') then begin
            i:=i+1;

            while (i<inputN) do begin
                GetLineWord(JHInput.Get(i),word,wordend);
                if (word='endglobals') then break
                else if ((word='constant') and CompareLineWord('integer',JHInput.Get(i),wordend,wordend)) then begin


                    GetLineToken(JHInput.Get(i),idn,wordend,wordend);
                    h:=-1;
                    if (GetAssigment(JHInput.Get(i), tem, wordend)) then begin
                        GetLineToken(tem,word,wordend);
                        if TryStrToInt(word,h) then begin
                            if (h<0) then h:=-2;
                        end else begin
                            h:=IntegerConstants.ValueOf(word);
                        end;
                        IntegerConstants.Add(idn,h);
                    end;
                end else if(not IsWhitespace(JHInput.Get(i)) ) then begin
                    word := JHInput.Get(i);
                    parseBigArray(word,i);
                    JHInput.Rewrite(i, word);
                end;
                i:=i+1;
            end;
            if (i=inputN) then raise JasserLineException(i-1,'[Internal error] An step prior structs has generated wrong globals header, report this bug.');





        end;
        i:=i+1;
    end;


    // iterate through the queue and parse the pending function lines
    for i := 0 to functionLines.Count - 1 do
        parseFunction( JHInput.Get(Integer(functionLines[i])),Integer(functionLines[i]) );

    for i := 0 to nativeLines.Count - 1 do begin

        if jasslib.AddNativeLine(JHInput.Get(Integer(nativeLines[i]) )) then begin
            SWriteLn(Nativesblock, JHInput.Get(Integer(nativeLines[i])));
        end;
        JHInput.Rewrite(Integer(nativeLines[i]), '');
    end;

    for i := 0 to hookLines.Count - 1 do begin
        EvaluateHook(JHInput.Get(Integer(hookLines[i])), Integer(hookLines[i]));
        JHInput.Prepend('//processed hook: ', Integer(hookLines[i]));
    end;
    i := 0;

    except
       on e:EAccessviolation do begin
           raise JasserLineDoubleException(i,'[Internal Error]',i,e.message);
       end;
    end;    
end;


end.
