Browse Source

Fundamental change: redesigned procedure and assembler inlining. It is now fully based on replacement rules on the level of the semantic checker / syntax tree.

{REGISTER} flag for variables and parameters: indicate that the variable / parameter should be stored in a register. This feature is intended a replacement of the previously present WITH .. IN .. OUT END feature of a CODE section. A register variable can be used within a CODE section by name. 

The {REGISTER} flag is a hint for the compiler to internally represent a variable or parameter by a register within the procedure context. A {REGISTER} parameter is not passed by register.
In an an inlined procedure, the compiler can decide to reuse the passed actual expression within the procedure. 

git-svn-id: https://svn-dept.inf.ethz.ch/svn/lecturers/a2/trunk@8922 8c9fc860-2736-0410-a75d-ab315db34111
felixf 6 years ago
parent
commit
70db38d976

+ 12 - 3
source/FoxAMD64Assembler.Mod

@@ -1326,6 +1326,7 @@ TYPE
 					NextChar;
 				| '@': symbol := symAt;
 					NextChar;
+									
 				| '$': NextChar;
 					IF char = '$' THEN
 						symbol := symPCOffset; NextChar;
@@ -1683,6 +1684,7 @@ TYPE
 
 			PROCEDURE GetOffsetFixup (CONST ident: ARRAY OF CHAR; VAR operand: Operand);
 			VAR scopeSymbol: SyntaxTree.Symbol;name: Basic.SegmentedName; symbol: IntermediateCode.Section;
+				type: IntermediateCode.Type;
 			BEGIN
 				IF labels.Find(ident) # NIL THEN RETURN END;
 				scopeSymbol := GetScopeSymbol (ident);
@@ -1707,9 +1709,17 @@ TYPE
 					END;
 					SetSymbol(operand,name,0,0,0);
 				ELSE
+					InitMem(operand,IntermediateCode.Bits32,InstructionSet.regRBP,(scopeSymbol.offsetInBits DIV 8)); (* or immediate ?? *)					
+					
+					(*SetSymbol(operand,name,0,0,0);*)
+				(*ELSE
 					Error("direct access to local variable offset forbidden");
+				*)
 				END;
+				operand.sizeInBytes := SHORTINT(scopeSymbol.type.resolved.sizeInBits DIV 8);
+				(*
 				operand.sizeInBytes := emitter.cpuBits;
+				*)
 			END GetOffsetFixup;
 
 			(* the following procedure is used to adapt sizes for relative jumps *)
@@ -1894,13 +1904,12 @@ TYPE
 							END;
 						ELSE
 							(* number or identifier (symbol) *)
-						InitImm(offset,size,0);
-
+							InitImm(offset,size,0);
 							IF (scope # NIL) & (symbol = symIdent) THEN (* identifier: must be a symbol *)
 								GetOffsetFixup (idents, offset);
 							END;
 
-							IF offset.symbol.name = "" THEN (* nothing could be fixuped, must be a number / constant *)
+							IF (offset.symbol.name = "") & (offset.register = none) THEN (* nothing could be fixuped, must be a number / constant *)
 								type := offset.type; currentFixup := ""; currentLabel := NIL;
 								IF ~Expression (offset.val, FALSE,type) THEN
 									RETURN FALSE;

+ 86 - 26
source/FoxAMDBackend.Mod

@@ -770,25 +770,33 @@ TYPE
 
 		PROCEDURE ResultRegister(CONST type: IntermediateCode.Type; part: LONGINT): LONGINT;
 		BEGIN
-			IF type.form IN IntermediateCode.Integer THEN
-				CASE type.sizeInBits OF
-					| 64:
-						IF cpuBits = 32 THEN
-							IF part = Low THEN RETURN EAX
-							ELSE RETURN EDX
+			IF type.length > 1 THEN
+				IF type.length = 4 THEN
+					RETURN XMM0;
+				ELSIF type.length = 8 THEN
+					RETURN YMM0;
+				END;
+			ELSE
+				IF type.form IN IntermediateCode.Integer THEN
+					CASE type.sizeInBits OF
+						| 64:
+							IF cpuBits = 32 THEN
+								IF part = Low THEN RETURN EAX
+								ELSE RETURN EDX
+								END;
+							ELSE
+								ASSERT(part = Low);
+								RETURN RAX
 							END;
-						ELSE
-							ASSERT(part = Low);
-							RETURN RAX
-						END;
-					| 32: ASSERT(part=Low); RETURN EAX
-					| 16: ASSERT(part=Low); RETURN AX
-					| 8: ASSERT(part=Low); RETURN AL
+						| 32: ASSERT(part=Low); RETURN EAX
+						| 16: ASSERT(part=Low); RETURN AX
+						| 8: ASSERT(part=Low); RETURN AL
+					END;
+				ELSIF ~backend.forceFPU THEN
+					RETURN XMM0
+				ELSE ASSERT(type.form = IntermediateCode.Float);ASSERT(part=Low);
+					RETURN ST0
 				END;
-			ELSIF ~backend.forceFPU THEN
-				RETURN XMM0
-			ELSE ASSERT(type.form = IntermediateCode.Float);ASSERT(part=Low);
-				RETURN ST0
 			END;
 		END ResultRegister;
 
@@ -1100,6 +1108,10 @@ TYPE
 		BEGIN RETURN operand.type.form = IntermediateCode.Float
 		END IsFloat;
 
+		PROCEDURE IsVector(CONST operand: IntermediateCode.Operand): BOOLEAN;
+		BEGIN RETURN operand.type.length > 1
+		END IsVector;
+
 		PROCEDURE IsComplex(CONST operand: IntermediateCode.Operand): BOOLEAN;
 		BEGIN RETURN (operand.type.form IN IntermediateCode.Integer) & (operand.type.sizeInBits > cpuBits)
 		END IsComplex;
@@ -1158,7 +1170,7 @@ TYPE
 			|IntermediateCode.trap: EmitTrap(instruction);
 			|IntermediateCode.br .. IntermediateCode.brlt: EmitBr(instruction)
 			|IntermediateCode.pop:
-				IF IsFloat(instruction.op1) THEN
+				IF IsFloat(instruction.op1) OR IsVector(instruction.op1) THEN
 					EmitPopFloat(instruction.op1)
 				ELSE
 					EmitPop(instruction.op1,Low);
@@ -1167,7 +1179,7 @@ TYPE
 					END;
 				END;
 			|IntermediateCode.push:
-				IF IsFloat(instruction.op1) THEN
+				IF IsFloat(instruction.op1) OR IsVector(instruction.op1) THEN
 					EmitPushFloat(instruction.op1)
 				ELSE
 					IF IsComplex(instruction.op1) THEN
@@ -3155,22 +3167,73 @@ TYPE
 		END EmitTrap;
 
 		PROCEDURE EmitAsm(CONST instruction: IntermediateCode.Instruction);
-		VAR reader: Streams.StringReader;  procedure: SyntaxTree.Procedure; scope: SyntaxTree.Scope;
+		VAR reader: Streams.StringReader;  procedure: SyntaxTree.Procedure;
 				len: LONGINT; symbol: SyntaxTree.Symbol; assembler: Assembler.Assembly;
 
 			inr, outr: IntermediateCode.Rules;
 			string: SyntaxTree.SourceCode;
 			i: LONGINT;
 			reg, dest: Assembler.Operand;
-			map: Assembler.RegisterMap;
+			map: Mapper;
 			register: LONGINT;
 			ticket: Ticket;
+			
+	TYPE Mapper = OBJECT (Assembler.RegisterMap)
+		VAR cg: CodeGeneratorAMD64; scope: SyntaxTree.Scope;
+		
+			PROCEDURE & InitMapper (cg: CodeGeneratorAMD64; scope: SyntaxTree.Scope);
+			BEGIN
+				SELF.cg := cg; SELF.scope := scope;
+			END InitMapper;
+			
+			
+			PROCEDURE Find(CONST name: ARRAY OF CHAR): LONGINT;
+			VAR register: LONGINT; symbol: SyntaxTree.Symbol; ticket: Ticket; 
+			BEGIN
+				register := Find^(name);
+				IF (register = InstructionSet.none) & (scope # NIL) THEN
+					symbol := scope.FindSymbol(Basic.MakeString(name));
+					IF symbol # NIL THEN 
+						WITH symbol: SyntaxTree.Variable DO
+							(*
+							TRACE(name,"variable",symbol.useRegister,symbol.registerNumber);
+							*)
+							IF symbol.preferRegister THEN
+								ticket := cg.virtualRegisters.Mapped(symbol.registerNumber,Low);
+								IF ticket = NIL THEN 
+									cg.MapVirtualRegister(symbol.registerNumber, IntermediateCode.GeneralPurposeRegister, IntermediateBackend.GetType(cg.module.system, symbol.type),Low);
+									ticket := cg.virtualRegisters.Mapped(symbol.registerNumber,Low);
+								END;
+								register := ticket.register;
+								(*TRACE(register);*)
+							END;
+						| SyntaxTree.Parameter DO
+							(*
+							TRACE(name,"parameter",symbol.useRegister,symbol.registerNumber);
+							*)
+							IF symbol.preferRegister THEN
+								ticket := cg.virtualRegisters.Mapped(symbol.registerNumber,Low);
+								IF ticket = NIL THEN 
+									cg.MapVirtualRegister(symbol.registerNumber, IntermediateCode.GeneralPurposeRegister, IntermediateBackend.GetType(cg.module.system, symbol.type),Low);
+									ticket := cg.virtualRegisters.Mapped(symbol.registerNumber,Low);
+								END;
+								register := ticket.register;
+							END;
+							
+						ELSE
+						END;
+					END;
+				END;
+				RETURN register;
+			END Find;
+		END Mapper;
+
 		BEGIN
 			IF instruction.op2.mode = IntermediateCode.ModeRule THEN	inr := instruction.op2.rule ELSE inr := NIL END;
 			IF instruction.op3.mode = IntermediateCode.ModeRule THEN outr := instruction.op3.rule ELSE outr := NIL END;
 			string := instruction.op1.string;
 
-			NEW(map);
+			NEW(map,SELF,instruction.scope);
 
 			IF inr # NIL THEN
 				FOR i := 0 TO LEN(inr)-1 DO
@@ -3195,10 +3258,9 @@ TYPE
 
 			symbol := in.symbol;
 			procedure := symbol(SyntaxTree.Procedure);
-			scope := procedure.procedureScope;
 			NEW(assembler,diagnostics,emitter);
 			assembler.useLineNumbers := Compiler.UseLineNumbers IN backend.flags;
-			assembler.Assemble(reader,instruction.textPosition,scope,in,in,module,procedure.access * SyntaxTree.Public # {}, procedure.isInline, map)	;
+			assembler.Assemble(reader,instruction.textPosition,instruction.scope,in,in,module,procedure.access * SyntaxTree.Public # {}, procedure.isInline, map)	;
 			error := error OR assembler.error;
 
 			IF outr # NIL THEN
@@ -3213,12 +3275,10 @@ TYPE
 					END;
 				END;
 			END;
-
 			(*
 			IntermediateCode.SetString(instruction.op1, string);
 			*)
 		END EmitAsm;
-
 	END CodeGeneratorAMD64;
 
 	BackendAMD64= OBJECT (IntermediateBackend.IntermediateBackend)

+ 2 - 3
source/FoxCSharpParser.Mod

@@ -867,8 +867,7 @@ KernelLog.Ln();
                 END;
                 NextSymbol;
             ELSIF Peek(Scanner.RealLiteral) THEN
-                realValue := SyntaxTree.NewRealValue(position, symbol.real);
-                realValue.SetSubtype(MapNumberType(symbol.numberType));
+                realValue := SyntaxTree.NewRealValue(position, symbol.real, symbol.numberType);
                 expression := realValue;
                 NextSymbol;
             ELSIF Peek(Scanner.CharacterLiteral) THEN
@@ -892,7 +891,7 @@ KernelLog.Ln();
                 expression := Expression();
                 Check(Scanner.RightParenthesis);
             ELSIF Optional(Scanner.This) THEN
-                expression := SyntaxTree.NewSelfDesignator(position);
+                expression := SyntaxTree.NewSelfDesignator(position,NIL);
             ELSIF Optional(Scanner.Base) THEN
                 Check(Scanner.Period);
                 position := symbol.position;

+ 1 - 1
source/FoxCSharpScanner.Mod

@@ -166,7 +166,7 @@ TYPE
         identifierString*: IdentifierString;
         string*: StringType;
         stringLength*: LONGINT;
-        numberType*: LONGINT;
+        numberType*: FoxScanner.SubType;
         integer*: LONGINT;
         hugeint*: HUGEINT;
         character*: CHAR;

+ 87 - 17
source/FoxGlobal.Mod

@@ -433,37 +433,77 @@ TYPE
 		END GenerateCellOffsets;
 
 		PROCEDURE GenerateVariableOffsets*(scope: SyntaxTree.Scope): BOOLEAN;
-		VAR variable: SyntaxTree.Variable; offset,size: LONGINT; alignment: LONGINT;
+		VAR variable: SyntaxTree.Variable; offset,size: LONGINT; alignment: LONGINT; s: SyntaxTree.Scope;
+			bscope: SyntaxTree.Scope;
 		BEGIN
 			IF scope IS SyntaxTree.RecordScope THEN (* increasing indices *)
 				RETURN GenerateRecordOffsets(scope(SyntaxTree.RecordScope).ownerRecord)
 			ELSIF scope IS SyntaxTree.CellScope THEN
 				RETURN GenerateCellOffsets(scope(SyntaxTree.CellScope).ownerCell);
 			ELSE (* module scope or procedure scope: decreasing indices *)
-				ASSERT((scope IS SyntaxTree.ModuleScope) OR (scope IS SyntaxTree.ProcedureScope));
-				offset := 0;
+				ASSERT((scope IS SyntaxTree.ModuleScope) OR (scope IS SyntaxTree.ProcedureScope) OR (scope IS SyntaxTree.BlockScope));
+	
+				bscope := scope; 
+				WHILE (bscope IS SyntaxTree.BlockScope) DO 
+					bscope := bscope.outerScope;
+				END; 
+				(*
+				IF scope IS SyntaxTree.BlockScope THEN
+					offset := scope.outerScope.currentVariableOffset;
+				ELSE
+					offset := 0;
+				END;
+				*)
+				offset := bscope.currentVariableOffset;
 
 				variable := scope.firstVariable;
 				WHILE (variable # NIL) DO
-					IF (variable.externalName # NIL) THEN
-						variable.SetOffset(offset)
-					ELSIF ~variable.fictive THEN
-						size := SizeOf(variable.type.resolved);
-						IF size < 0 THEN RETURN FALSE END;
-						DEC(offset,size);
-
-						IF variable.alignment > 0 THEN
-							Basic.Align(offset, -variable.alignment*dataUnit);
-						ELSE
-							alignment := AlignmentOf(SELF.variableAlignment,variable.type.resolved);
-							Basic.Align(offset,-alignment);
+					IF variable.offsetInBits = MIN(LONGINT) THEN
+						IF (variable.externalName # NIL) THEN
+							variable.SetOffset(offset)
+						ELSIF ~variable.fictive & ~variable.preferRegister THEN
+							size := SizeOfVariable(variable);
+							IF size < 0 THEN RETURN FALSE END;
+							DEC(offset,size);
+							IF variable.alignment > 0 THEN
+								Basic.Align(offset, -variable.alignment*dataUnit);
+							ELSE
+								alignment := AlignmentOf(SELF.variableAlignment,variable.type.resolved);
+								Basic.Align(offset,-alignment);
+							END;
+							variable.SetOffset(offset);
 						END;
-
-						variable.SetOffset(offset);
 					END;
 					variable := variable.nextVariable;
 				END;
 			END;
+			bscope.SetCurrentVariableOffset(offset);
+			IF offset < bscope.minVariableOffset THEN
+				bscope.SetMinVariableOffset(offset);
+			END;
+			(*
+			WHILE (scope IS SyntaxTree.BlockScope) DO
+				TRACE(scope, scope.minVariableOffset); 
+				IF scope.minVariableOffset < scope.outerScope.minVariableOffset THEN
+					scope.outerScope.SetMinVariableOffset(scope.minVariableOffset);
+				END;
+				scope := scope.outerScope; 
+			END;
+			*)
+			(*
+			WITH scope: SyntaxTree.ProcedureScope DO
+				s := scope.firstScope;
+				WHILE (s # NIL) DO (* block scopes *)
+					IF ~GenerateVariableOffsets(s) THEN RETURN FALSE END;
+					s := s.nextScope;
+				END;
+			| SyntaxTree.BlockScope DO
+				IF offset < scope.outerScope.minVariableOffset THEN 
+					scope.outerScope.SetMinVariableOffset(offset);
+				END;
+			ELSE
+			END;
+			*)
 			RETURN TRUE
 		END GenerateVariableOffsets;
 
@@ -650,6 +690,36 @@ TYPE
 			END;
 		END SizeOfParameter;
 
+		PROCEDURE SizeOfVariable*(var: SyntaxTree.Variable):LONGINT;
+		BEGIN
+			IF (var.type.resolved IS SyntaxTree.MathArrayType) OR (var.type.resolved IS SyntaxTree.ArrayType) THEN
+				IF (var.kind IN {SyntaxTree.ConstParameter,SyntaxTree.VarParameter}) THEN
+					RETURN addressSize;
+				ELSE
+					RETURN SizeOf(var.type)
+				END;
+			ELSIF var.type.resolved IS SyntaxTree.RangeType THEN
+				IF var.kind = SyntaxTree.VarParameter THEN
+					RETURN addressSize
+				ELSE
+					RETURN SizeOf(rangeType) (* array range components are materialized on stack for both value and const parameters *)
+				END
+			ELSIF var.type.resolved IS SyntaxTree.RecordType THEN
+				IF (var.kind IN {SyntaxTree.ConstParameter,SyntaxTree.VarParameter}) THEN
+					RETURN 2*addressSize
+				ELSE
+					RETURN SizeOf(var.type);
+				END;
+			ELSIF var.kind = SyntaxTree.VarParameter THEN
+				RETURN addressSize
+			ELSIF var.kind = SyntaxTree.ConstParameter THEN
+				RETURN SizeOf(var.type)
+			ELSE
+				RETURN SizeOf(var.type);
+			END;
+		END SizeOfVariable;
+
+
 		PROCEDURE AlignmentOf*(CONST alignment: Alignment;type: SyntaxTree.Type): LONGINT;
 		VAR result: LONGINT;
 		BEGIN

File diff suppressed because it is too large
+ 249 - 312
source/FoxIntermediateBackend.Mod


+ 10 - 2
source/FoxIntermediateCode.Mod

@@ -121,6 +121,7 @@ TYPE
 		subtype-: SHORTINT; (* for special backend instruction *)
 		textPosition-: Basic.Position; (* for error handling and tracking (findPC) *)
 		pc-: LONGINT; (* backend program counter (in bits) for debugging and for label fixups in backend *)
+		scope-: SyntaxTree.Scope; (* will replace rules *)
 		op1*,op2*,op3*: Operand; (* first operand typically provides the result, if any *)
 	END;
 
@@ -770,7 +771,7 @@ TYPE
 
 	BEGIN
 		(* nop - no operation, may be used for optimisations *)
-		AddFormat(nop, "nop", Undef, Undef, Undef, {});
+		AddFormat(nop, "nop", UndefReg, Undef, Undef, {});
 		(* mov dest src - mov content of src to dest, if a third parameter is provided (set to a register),
 			it has no meaning for interpreters or execution but provides a "reuse" hint for register allocators *)
 		AddFormat(mov, "mov", RegMem, RegMemImm, UndefReg, {SameSize12,Op1IsDestination});
@@ -950,6 +951,12 @@ TYPE
 		op.symbol.name := symbol;
 		op.symbol.fingerprint := fp;
 	END SetSymbol;
+	
+	PROCEDURE SetScope*(VAR instr: Instruction; scope: SyntaxTree.Scope);
+	BEGIN
+		instr.scope := scope;
+	END SetScope;
+	
 
 	PROCEDURE SetIntValue*(VAR op: Operand; intValue: HUGEINT);
 	BEGIN op.intValue := intValue
@@ -1218,7 +1225,7 @@ TYPE
 	END DenotesType;
 
 	PROCEDURE GetType*(system: Global.System; type: SyntaxTree.Type): Type;
-	VAR t: Type;
+	VAR t: Type; length: WORD;
 	BEGIN
 		type := type.resolved;
 		IF type IS SyntaxTree.CharacterType THEN
@@ -1249,6 +1256,7 @@ TYPE
 			WITH type: SyntaxTree.MathArrayType DO
 				IF type.form = SyntaxTree.Static THEN
 					t := GetType(system, type.arrayBase);
+					length := t.length;
 					ASSERT(t.length = 1);
 					ToVectorType(t, type.staticLength);
 					RETURN t

+ 11 - 11
source/FoxParser.Mod

@@ -69,7 +69,7 @@ CONST
 
 	CellType = 'cell' [Flags] [PortList] [';'] DeclarationSequence [Body] 'end' [Identifier].
 
-	ObjectType = 'object' | 'object' [Flags] ['(' (QualifiedIdentifier | ArrayType) ')'] DeclarationSequence [Body] 'end' [Identifier] .
+	ObjectType = 'object' | 'object' [Flags] ['(' (QualifiedIdentifier) ')'] DeclarationSequence [Body] 'end' [Identifier] .
 
 	ProcedureType = 'procedure' [Flags] [FormalParameters].
 
@@ -775,7 +775,7 @@ TYPE
 			IF Trace THEN S( "Designator" ) END;
 			position := token.position;
 			IF Optional(Scanner.Self) THEN
-				designator := SyntaxTree.NewSelfDesignator(position);
+				designator := SyntaxTree.NewSelfDesignator(position, NIL);
 			ELSIF Optional(Scanner.Result) THEN
 				designator := SyntaxTree.NewResultDesignator(position);
 			(* ADDRESS AND SIZE can be type identifiers used for type conversion *)
@@ -797,7 +797,7 @@ TYPE
 							Check( Scanner.RightParenthesis )
 						END;
 					END;
-					designator := SyntaxTree.NewBuiltinCallDesignator(position,Global.New, NIL, expressionList);
+					designator := SyntaxTree.NewBuiltinCallDesignator(position, NIL, Global.New, NIL, expressionList);
 					designator(SyntaxTree.BuiltinCallDesignator).SetReturnType(qualifiedType);
 					(* special case: NEW Type() *)
 				END;
@@ -857,7 +857,7 @@ TYPE
 		BEGIN
 			IF Trace THEN S( "Set" ) END;
 
-			set := SyntaxTree.NewSet(token.position);
+			set := SyntaxTree.NewSet(token.position,SyntaxTree.NewExpressionList());
 			Check(Scanner.LeftBrace);
 			IF ~Optional(Scanner.RightBrace) THEN
 				REPEAT
@@ -875,7 +875,7 @@ TYPE
 		PROCEDURE MathArray(): SyntaxTree.Expression;
 		VAR array: SyntaxTree.MathArrayExpression; element: SyntaxTree.Expression;
 		BEGIN
-			array := SyntaxTree.NewMathArrayExpression(token.position);
+			array := SyntaxTree.NewMathArrayExpression(token.position, SyntaxTree.NewExpressionList());
 			IF ~Optional(Scanner.RightBracket) THEN
 				REPEAT
 					element := Expression();
@@ -903,8 +903,7 @@ TYPE
 					ELSIF (token.numberType = Scanner.Hugeint) THEN
 						factor := SyntaxTree.NewIntegerValue(position, token.hugeint);
 					ELSIF (token.numberType = Scanner.Real) OR (token.numberType = Scanner.Longreal) THEN
-						factor := SyntaxTree.NewRealValue( position, token.real);
-						factor(SyntaxTree.RealValue).SetSubtype(token.numberType);
+						factor := SyntaxTree.NewRealValue( position, token.real, token.numberType);
 					ELSE HALT( 100 )
 					END;
 					NextToken;
@@ -927,8 +926,7 @@ TYPE
 					factor := SyntaxTree.NewNilValue( position );
 					NextToken;
 			| Scanner.Imag:
-					factor := SyntaxTree.NewComplexValue(position, 0, 1);
-					factor(SyntaxTree.ComplexValue).SetSubtype(Scanner.Real);
+					factor := SyntaxTree.NewComplexValue(position, 0, 1, Scanner.Real);
 					NextToken;
 			| Scanner.True:
 					factor := SyntaxTree.NewBooleanValue( position, TRUE );
@@ -1397,7 +1395,7 @@ TYPE
 		(** Code = {  any \ 'end' \ 'with' } ['with' {('in'|'out') StatementSequence}] . **)
 		PROCEDURE Code(outer: SyntaxTree.Statement): SyntaxTree.Code;
 		VAR startPos: Position; endPos, i ,len: LONGINT; codeString: Scanner.StringType; code: SyntaxTree.Code;
-			end: Scanner.Symbol; in, out: BOOLEAN; statements, rules: SyntaxTree.StatementSequence;
+			end: Scanner.Symbol; (*in, out: BOOLEAN; statements, rules: SyntaxTree.StatementSequence;*)
 		BEGIN
 			startPos := token.position;
 			end := scanner.SkipToEndOfCode(startPos.start, endPos, token);
@@ -1408,10 +1406,11 @@ TYPE
 					codeString := Strings.ConcatToNew (codeString^, token.string^);
 				END;
 			END;
-			IF (end = Scanner.End) OR (end = Scanner.With) THEN
+			IF (end = Scanner.End) (*OR (end = Scanner.With)*) THEN
 				code := SyntaxTree.NewCode(startPos,outer);
 				i := 0; len := LEN(codeString^);
 				code.SetSourceCode(codeString,len);
+				(*
 				IF (end = Scanner.With) & Mandatory(Scanner.With) THEN
 					in := Optional(Scanner.In);
 					out := Optional(Scanner.Out);
@@ -1425,6 +1424,7 @@ TYPE
 						out := Optional(Scanner.Out);
 					END;
 				END;
+				*)
 			END;
 			RETURN code;
 		END Code;

+ 41 - 30
source/FoxPrintout.Mod

@@ -731,19 +731,10 @@ TYPE
 
 		PROCEDURE VisitInlineCallDesignator*(x: SyntaxTree.InlineCallDesignator);
 		BEGIN
+			Scope(x.block.scope); 
 			VisitStatementBlock(x.block);
 		END VisitInlineCallDesignator;
 
-		PROCEDURE VisitStatementDesignator*(x: SyntaxTree.StatementDesignator);
-		BEGIN
-			Indent; Keyword("STATEMENT-DESIGNATOR ");
-			IF x.result # NIL THEN
-				Keyword("RETURNS ");
-				Expression(x.result)
-			END;
-			Indent; Statement(x.statement);
-		END VisitStatementDesignator;
-
 		PROCEDURE VisitBuiltinCallDesignator*(x: SyntaxTree.BuiltinCallDesignator);
 		BEGIN
 			IF x.left # NIL THEN
@@ -847,7 +838,7 @@ TYPE
 				END;
 				w.String(string);
 			ELSE
-				w.Float(value,64)
+				w.Float(value,31)
 			END;
 		END FormatedFloat;
 
@@ -945,12 +936,13 @@ TYPE
 				Access(x.access);
 				w.String("}");
 				IF x.offsetInBits # MIN(LONGINT) THEN
-					w.String("@"); w.Hex(x.offsetInBits,1);
-				END;
-				IF x.type # NIL THEN
-				IF x.type.resolved.alignmentInBits >=0 THEN
-					w.String("@@"); w.Hex(x.type.resolved.alignmentInBits,1);
-				END;
+					w.String("@ofs="); w.Int(x.offsetInBits DIV 8,1);
+				ELSE
+					IF x.type # NIL THEN
+						IF x.type.resolved.alignmentInBits #0 THEN
+							w.String("@align="); w.Int(x.type.resolved.alignmentInBits DIV 8,1);
+						END;
+					END;
 				END;
 				EndComment;
 			END;
@@ -1056,6 +1048,8 @@ TYPE
 					Value(Global.NameAligned,x.alignment,first)
 				ELSIF x.fictive THEN
 					Value(Global.NameFictive, x.fictiveOffset, first);
+				ELSIF x.preferRegister THEN
+					Flag(Global.NameRegister,first);
 				END;
 				IF x.untraced THEN
 					Flag(Global.NameUntraced,first)
@@ -1094,6 +1088,33 @@ TYPE
 			w.DecIndent
 		END VariableList;
 
+		PROCEDURE AliasList(x: SyntaxTree.Alias);
+		VAR next: SyntaxTree.Alias;
+		BEGIN
+			w.IncIndent;
+			WHILE(x # NIL) DO
+				next := x.nextAlias;
+				IF (x.access # SyntaxTree.Hidden) OR (mode > SourceCode) THEN
+					Indent;
+					Comments(x.comment, x, FALSE);
+					PrintSymbol(x); 
+					IF x.expression # NIL THEN
+						w.String( " := " ); Expression (x.expression);
+					END;
+					IF x.access # SyntaxTree.Hidden THEN
+						w.String(": ");
+						Type(x.type);
+					ELSE
+						w.String(": ");
+						ShortType(x.type);
+					END;
+					w.String("; ");
+				END;
+				x := next;
+			END;
+			w.DecIndent
+		END AliasList;
+		
 		PROCEDURE VisitParameter*(x: SyntaxTree.Parameter);
 		BEGIN
 			IF (x.access # SyntaxTree.Hidden) THEN
@@ -1267,7 +1288,8 @@ TYPE
 		END VisitProcedure;
 
 		PROCEDURE VisitOperator*(x: SyntaxTree.Operator);
-		VAR type: SyntaxTree.ProcedureType; first: BOOLEAN;
+		VAR type: SyntaxTree.ProcedureType;
+			first: BOOLEAN;
 		BEGIN
 			IF Visible(x) THEN
 				Indent;
@@ -1447,6 +1469,7 @@ TYPE
 			IF x.firstConstant # NIL THEN ConstantList(x.firstConstant); END;
 			IF x.firstTypeDeclaration # NIL THEN TypeDeclarationList(x.firstTypeDeclaration); END;
 			IF x.firstVariable # NIL THEN Indent;  Keyword("VAR " );  VariableList(x.firstVariable);  END;
+			IF x.firstAlias # NIL THEN Indent; Keyword("ALIAS "); AliasList(x.firstAlias) END; 
 			IF x.procedures # NIL THEN w.Ln; ProcedureList(x.procedures) END;
 			currentScope := prevScope;
 		END Scope;
@@ -1781,21 +1804,9 @@ TYPE
 		END Code;
 
 		PROCEDURE VisitCode*(x: SyntaxTree.Code);
-		VAR in, out: BOOLEAN;
 		BEGIN
 			Indent; Keyword("CODE");
 			Code(x);
-			in := x.inRules.Length()>0;
-			out := x.outRules.Length() >0;
-			IF in OR out THEN
-				Indent; Keyword("WITH ");
-				IF in THEN
-					Indent; Keyword("IN "); StatementSequence(x.inRules)
-				END;
-				IF out THEN
-					Indent; Keyword("OUT "); StatementSequence(x.outRules)
-				END;
-			END;
 			Indent; Keyword("END");
 		END VisitCode;
 

+ 2 - 1
source/FoxScanner.Mod

@@ -22,6 +22,7 @@ TYPE
 	StringType* = Strings.String;
 	IdentifierType* = StringPool.Index;
 	IdentifierString*= ARRAY MaxIdentifierLength+1 OF CHAR;
+	SubType*= SHORTINT;
 
 CONST
 
@@ -180,7 +181,7 @@ TYPE
 		identifierString*: IdentifierString; (* cache of identifier's string *)
 		string*: StringType;  (* string or identifier *)
 		stringLength*: LONGINT; (* length of string, if stringLength = 2 then this may be interpreted as character and integer = ORD(ch) *)
-		numberType*: LONGINT;  (* Integer, HugeInteger, Real or Longreal *)
+		numberType*: SubType;  (* Integer, HugeInteger, Real or Longreal *)
 		integer*: LONGINT;
 		hugeint*: HUGEINT;  (*! unify longint and hugeint *)
 		character*: CHAR;

File diff suppressed because it is too large
+ 261 - 186
source/FoxSemanticChecker.Mod


File diff suppressed because it is too large
+ 208 - 314
source/FoxSyntaxTree.Mod


Some files were not shown because too many files changed in this diff