Compare commits

...

9 Commits

Author SHA1 Message Date
Rairii
54404a1fa6 asm: fix the case for non-exported function that returns a value 2025-04-11 13:04:58 +01:00
Rairii
301c583ce2 asm: fix referencing arguments where function is not exported and argument list may be unknown 2025-04-11 12:59:29 +01:00
Rairii
2dca25d95b lib: fix creating an argument variable where function is not exported therefore arguments are unknown 2025-04-11 12:58:44 +01:00
Rairii
7202da81ea asm: fix culture issues by setting current thread culture when inside the assembler 2025-04-11 12:29:37 +01:00
Rairii
0f6e7a5bcb lib: use single static cultureinfo instead of allocating every time 2025-04-11 12:28:50 +01:00
Rairii
056cd7a9a1 tests: add test for extended floating point variables 2025-04-11 12:05:47 +01:00
Rairii
1767aeec9f tests: fix compilation with vs2022 2025-04-11 11:59:42 +01:00
Rairii
82ddafd61e ifpslib: fix extended float for certain regions
ExtF80 always uses '.' for number decimal separator, ensure that english culture info is used to match it.
2025-04-06 19:47:12 +01:00
zc
adc9a2dde1 cc: add timer for each stage (via compile time config)
cc: optimise lexer for speed (~10x speed improvement)
cc: implement OperatorParser class as per TODO in original codebase (seems refactoring chains of parser-combinators leads to at least SOME speed improvement)
2023-07-11 17:57:57 +01:00
19 changed files with 1314 additions and 281 deletions

View File

@ -9,6 +9,8 @@ using IFPSLib.Emit.FDecl;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Collections; using System.Collections;
using System.ComponentModel; using System.ComponentModel;
using System.Globalization;
using System.Threading;
namespace IFPSAsmLib namespace IFPSAsmLib
{ {
@ -98,6 +100,7 @@ namespace IFPSAsmLib
public static class Assembler public static class Assembler
{ {
private static readonly CultureInfo s_Culture = new CultureInfo("en");
private static IEnumerable<ParsedBody> OfType(this IEnumerable<ParsedBody> self, ElementParentType type) private static IEnumerable<ParsedBody> OfType(this IEnumerable<ParsedBody> self, ElementParentType type)
{ {
return self.Where(x => x.Element.ParentType == type); return self.Where(x => x.Element.ParentType == type);
@ -534,6 +537,16 @@ namespace IFPSAsmLib
return function.CreateArgumentVariable(i); return function.CreateArgumentVariable(i);
} }
value = value.ToLower(); value = value.ToLower();
// For a non-exported function, allow use of hardcoded Argx to refer to unknown arguments
if (!function.Exported)
{
if (value.StartsWith(Constants.VARIABLE_ARG_PREFIX)) {
if (!int.TryParse(value.Substring(Constants.VARIABLE_ARG_PREFIX.Length), out var argIdx)) return null;
if (function.ReturnArgument == null) argIdx--;
if (argIdx < 0) return null;
return function.CreateArgumentVariable(argIdx);
}
}
if (value == Constants.VARIABLE_RET) return function.CreateReturnVariable(); if (value == Constants.VARIABLE_RET) return function.CreateReturnVariable();
if (!value.StartsWith(Constants.VARIABLE_LOCAL_PREFIX)) return null; if (!value.StartsWith(Constants.VARIABLE_LOCAL_PREFIX)) return null;
if (!int.TryParse(value.Substring(Constants.VARIABLE_LOCAL_PREFIX.Length), out var idx)) return null; if (!int.TryParse(value.Substring(Constants.VARIABLE_LOCAL_PREFIX.Length), out var idx)) return null;
@ -856,7 +869,7 @@ namespace IFPSAsmLib
} }
} }
public static Script Assemble(List<ParsedBody> parsed) private static Script AssembleImpl(List<ParsedBody> parsed)
{ {
int version = Script.VERSION_HIGHEST; int version = Script.VERSION_HIGHEST;
{ {
@ -939,6 +952,21 @@ namespace IFPSAsmLib
return ret; return ret;
} }
public static Script Assemble(List<ParsedBody> parsed)
{
// Set the current thread's culture to english when assembling, to ensure float/double/decimal parsing works correctly.
var currentCulture = Thread.CurrentThread.CurrentCulture;
Thread.CurrentThread.CurrentCulture = s_Culture;
try
{
return AssembleImpl(parsed);
}
finally
{
Thread.CurrentThread.CurrentCulture = currentCulture;
}
}
public static Script Assemble(string str) => Assemble(Parser.Parse(str)); public static Script Assemble(string str) => Assemble(Parser.Parse(str));
} }
} }

View File

@ -71,6 +71,7 @@ namespace IFPSAsmLib
internal const string VARIABLE_RET = "retval"; internal const string VARIABLE_RET = "retval";
internal const string VARIABLE_LOCAL_PREFIX = "var"; internal const string VARIABLE_LOCAL_PREFIX = "var";
internal const string VARIABLE_ARG_PREFIX = "arg";
internal const string LABEL_NULL = "null"; internal const string LABEL_NULL = "null";
} }

Binary file not shown.

View File

@ -0,0 +1,820 @@
.version 23
.entry !MAIN
.type primitive(Pointer) Pointer
.type primitive(U32) U32
.type primitive(Variant) Variant
.type primitive(PChar) PChar
.type primitive(Currency) Currency
.type primitive(Extended) Extended
.type primitive(Double) Double
.type primitive(Single) Single
.type primitive(S64) S64
.type primitive(String) String
.type primitive(U32) U32_2
.type primitive(S32) S32
.type primitive(S16) S16
.type primitive(U16) U16
.type primitive(S8) S8
.type primitive(String) String_2
.type primitive(UnicodeString) UnicodeString
.type primitive(UnicodeString) UnicodeString_2
.type primitive(String) String_3
.type primitive(UnicodeString) UnicodeString_3
.type primitive(WideString) WideString
.type primitive(WideChar) WideChar
.type primitive(WideChar) WideChar_2
.type primitive(Char) Char
.type primitive(U8) U8
.type primitive(U16) U16_2
.type primitive(U32) U32_3
.type(export) primitive(U8) BOOLEAN
.type primitive(U8) U8_2
.type(export) class(TBUTTON) TBUTTON
.type record(U32_2,S32,S32,S32,U32_2,U32_2,U16,U16,U16,U16,U16,S32,S32,U32_2,U32_2,PChar,PChar,S32,S32) Type30
.type record(S32,PChar,PChar,PChar,U32_2) Type31
.type record(S32,S32) Type32
.type(export) record(S32,S32,S32,S32) TRECT
.type record(U32_2,U32_2,TRECT,TRECT,Type32) Type34
.type(export) class(TWIZARDFORM) TWIZARDFORM
.type(export) class(TRICHEDITVIEWER) TRICHEDITVIEWER
.type(export) class(TOBJECT) TOBJECT
.type(export) class(TNEWRADIOBUTTON) TNEWRADIOBUTTON
.type(export) class(TCONTROL) TCONTROL
.type(export) class(TCOMPONENT) TCOMPONENT
.type(export) class(TNEWNOTEBOOKPAGE) TNEWNOTEBOOKPAGE
.type(export) funcptr(void(__in)) TNOTIFYEVENT
.type(export) class(TWINCONTROL) TWINCONTROL
.global TBUTTON Global0
.function(export) void !MAIN()
ret
.function(import) external dll("gdi32.dll","GetDeviceCaps") __stdcall returnsval gdi32.dll!GetDeviceCaps(__in __unknown,__in __unknown)
.function(import) external dll("comdlg32.dll","PrintDlgA") __stdcall returnsval comdlg32.dll!PrintDlgA(__out __unknown)
.function(import) external dll("gdi32.dll","DeleteDC") __stdcall returnsval gdi32.dll!DeleteDC(__in __unknown)
.function(import) external dll("gdi32.dll","StartDocA") __stdcall returnsval gdi32.dll!StartDocA(__in __unknown,__in __unknown)
.function(import) external dll("gdi32.dll","StartPage") __stdcall returnsval gdi32.dll!StartPage(__in __unknown)
.function(import) external dll("gdi32.dll","EndPage") __stdcall returnsval gdi32.dll!EndPage(__in __unknown)
.function(import) external dll("gdi32.dll","EndDoc") __stdcall returnsval gdi32.dll!EndDoc(__in __unknown)
.function(import) external dll("gdi32.dll","AbortDoc") __stdcall returnsval gdi32.dll!AbortDoc(__in __unknown)
.function(import) external dll("user32.dll","SendMessageA") __stdcall returnsval user32.dll!SendMessageA(__in __unknown,__in __unknown,__in __unknown,__out __unknown)
.function(import) external dll("user32.dll","SendMessageA") __stdcall returnsval user32.dll!SendMessageA_2(__in __unknown,__in __unknown,__in __unknown,__out __unknown)
.function(export) BOOLEAN ISUPGRADE()
pushtype UnicodeString_2 ; StackCount = 1
pushtype TWIZARDFORM ; StackCount = 2
pushvar Var2 ; StackCount = 3
call WIZARDFORM
pop ; StackCount = 2
pushvar Var1 ; StackCount = 3
call TWIZARDFORM->PREVAPPDIR
pop ; StackCount = 2
pop ; StackCount = 1
ne RetVal, Var1, UnicodeString_3("")
ret
.function(import) external internal returnsval WIZARDFORM()
.function(import) external class(TWIZARDFORM, PREVAPPDIR) __pascal void TWIZARDFORM->PREVAPPDIR(__in __unknown,__in __unknown)
.function(export) BOOLEAN ISPORTABLE()
pushtype UnicodeString_2 ; StackCount = 1
pushtype UnicodeString_2 ; StackCount = 2
assign Var2, UnicodeString_3("{param:portable|0}")
pushvar Var1 ; StackCount = 3
call EXPANDCONSTANT
pop ; StackCount = 2
pop ; StackCount = 1
eq RetVal, Var1, WideChar_2("1")
pop ; StackCount = 0
ret
.function(import) external internal returnsval EXPANDCONSTANT(__in __unknown)
.function(export) BOOLEAN SELECTPRINTER(__out Type30 Arg1)
pushtype S32 ; StackCount = 1
pushtype Type30 ; StackCount = 2
assign Var2, Arg1
pushvar Var1 ; StackCount = 3
call SIZEOF
pop ; StackCount = 2
pop ; StackCount = 1
assign Arg1[0], Var1
pop ; StackCount = 0
pushtype TWIZARDFORM ; StackCount = 1
pushvar Var1 ; StackCount = 2
call WIZARDFORM
pop ; StackCount = 1
pushvar Arg1[1] ; StackCount = 2
call TWINCONTROL->HANDLE
pop ; StackCount = 1
pop ; StackCount = 0
assign Arg1[2], S32(0)
assign Arg1[3], S32(0)
assign Arg1[4], S32(0)
assign Arg1[5], S32(262404)
assign Arg1[6], S32(0)
assign Arg1[7], S32(0)
assign Arg1[8], S32(0)
assign Arg1[9], S32(0)
assign Arg1[10], S32(0)
assign Arg1[11], S32(0)
assign Arg1[12], S32(0)
assign Arg1[13], S32(0)
assign Arg1[14], S32(0)
assign Arg1[15], UnicodeString_3("")
assign Arg1[16], UnicodeString_3("")
assign Arg1[17], S32(0)
assign Arg1[18], S32(0)
pushtype Pointer ; StackCount = 1
setptr Var1, Arg1
pushvar RetVal ; StackCount = 2
call comdlg32.dll!PrintDlgA
pop ; StackCount = 1
pop ; StackCount = 0
ret
.function(import) external internal returnsval SIZEOF()
.function(import) external class(TWINCONTROL, HANDLE) __pascal void TWINCONTROL->HANDLE(__in __unknown,__in __unknown)
.function(export) BOOLEAN PRINTRICHEDIT(__in Type30 Arg1,__in TRICHEDITVIEWER Arg2,__in UnicodeString_2 Arg3,__in Double Arg4,__in Double Arg5,__in Double Arg6,__in Double Arg7)
pushtype Type31 ; StackCount = 1
pushtype Type34 ; StackCount = 2
pushtype U32_2 ; StackCount = 3
pushtype S32 ; StackCount = 4
pushtype S32 ; StackCount = 5
pushtype S32 ; StackCount = 6
pushtype S32 ; StackCount = 7
pushtype S32 ; StackCount = 8
pushtype S32 ; StackCount = 9
pushtype S32 ; StackCount = 10
pushtype S32 ; StackCount = 11
pushtype S32 ; StackCount = 12
pushtype S32 ; StackCount = 13
pushtype S32 ; StackCount = 14
assign Var3, Arg1[4]
pushtype TRICHEDITVIEWER ; StackCount = 15
assign Var15, Arg2
pushvar Var4 ; StackCount = 16
call TWINCONTROL->HANDLE
pop ; StackCount = 15
pop ; StackCount = 14
pushtype Type31 ; StackCount = 15
assign Var15, Var1
pushvar Var1[0] ; StackCount = 16
call SIZEOF
pop ; StackCount = 15
pop ; StackCount = 14
assign Var1[1], Arg3
assign Var1[2], UnicodeString_3("")
assign Var1[3], UnicodeString_3("")
assign Var1[4], S32(0)
pushtype BOOLEAN ; StackCount = 15
pushtype S32 ; StackCount = 16
pushtype Type31 ; StackCount = 17
assign Var17, Var1
pushtype U32_2 ; StackCount = 18
assign Var18, Var3
pushvar Var16 ; StackCount = 19
call gdi32.dll!StartDocA
pop ; StackCount = 18
pop ; StackCount = 17
pop ; StackCount = 16
le Var15, Var16, S32(0)
pop ; StackCount = 15
sfz Var15
pop ; StackCount = 14
jf loc_137
ret
loc_137:
pushtype S32 ; StackCount = 15
assign Var15, S32(88)
pushtype U32_2 ; StackCount = 16
assign Var16, Var3
pushvar Var8 ; StackCount = 17
call gdi32.dll!GetDeviceCaps
pop ; StackCount = 16
pop ; StackCount = 15
pop ; StackCount = 14
pushtype S32 ; StackCount = 15
assign Var15, S32(90)
pushtype U32_2 ; StackCount = 16
assign Var16, Var3
pushvar Var9 ; StackCount = 17
call gdi32.dll!GetDeviceCaps
pop ; StackCount = 16
pop ; StackCount = 15
pop ; StackCount = 14
pushtype S32 ; StackCount = 15
assign Var15, S32(8)
pushtype U32_2 ; StackCount = 16
assign Var16, Var3
pushvar Var6 ; StackCount = 17
call gdi32.dll!GetDeviceCaps
pop ; StackCount = 16
pop ; StackCount = 15
pop ; StackCount = 14
mul Var6, S32(1440)
div Var6, Var8
pushtype S32 ; StackCount = 15
assign Var15, S32(10)
pushtype U32_2 ; StackCount = 16
assign Var16, Var3
pushvar Var7 ; StackCount = 17
call gdi32.dll!GetDeviceCaps
pop ; StackCount = 16
pop ; StackCount = 15
pop ; StackCount = 14
mul Var7, S32(1440)
div Var7, Var9
pushtype S32 ; StackCount = 15
assign Var15, S32(110)
pushtype U32_2 ; StackCount = 16
assign Var16, Var3
pushvar Var10 ; StackCount = 17
call gdi32.dll!GetDeviceCaps
pop ; StackCount = 16
pop ; StackCount = 15
pop ; StackCount = 14
mul Var10, S32(1440)
div Var10, Var8
pushtype S32 ; StackCount = 15
assign Var15, S32(111)
pushtype U32_2 ; StackCount = 16
assign Var16, Var3
pushvar Var11 ; StackCount = 17
call gdi32.dll!GetDeviceCaps
pop ; StackCount = 16
pop ; StackCount = 15
pop ; StackCount = 14
mul Var11, S32(1440)
div Var11, Var9
pushtype S32 ; StackCount = 15
assign Var15, S32(112)
pushtype U32_2 ; StackCount = 16
assign Var16, Var3
pushvar Var12 ; StackCount = 17
call gdi32.dll!GetDeviceCaps
pop ; StackCount = 16
pop ; StackCount = 15
pop ; StackCount = 14
mul Var12, S32(1440)
div Var12, Var8
pushtype S32 ; StackCount = 15
assign Var15, S32(113)
pushtype U32_2 ; StackCount = 16
assign Var16, Var3
pushvar Var13 ; StackCount = 17
call gdi32.dll!GetDeviceCaps
pop ; StackCount = 16
pop ; StackCount = 15
pop ; StackCount = 14
mul Var13, S32(1440)
div Var13, Var9
pushtype Extended ; StackCount = 15
pushtype Double ; StackCount = 16
assign Var16, Arg4
mul Var16, S32(1440)
assign Var15, Var16
pop ; StackCount = 15
pushvar Var5 ; StackCount = 16
call ROUND
pop ; StackCount = 15
pop ; StackCount = 14
sub Var5, Var12
pushtype BOOLEAN ; StackCount = 15
lt Var15, Var5, S32(0)
sfz Var15
pop ; StackCount = 14
jf loc_3ef
assign Var5, S32(0)
loc_3ef:
pushtype Pointer ; StackCount = 15
setptr Var15, Var2
setptr Var15, Var15[2]
setptr Var15, Var15[0]
assign Var15, Var5
pop ; StackCount = 14
pushtype Extended ; StackCount = 15
pushtype Double ; StackCount = 16
assign Var16, Arg5
mul Var16, S32(1440)
assign Var15, Var16
pop ; StackCount = 15
pushvar Var5 ; StackCount = 16
call ROUND
pop ; StackCount = 15
pop ; StackCount = 14
sub Var5, Var13
pushtype BOOLEAN ; StackCount = 15
lt Var15, Var5, S32(0)
sfz Var15
pop ; StackCount = 14
jf loc_4a9
assign Var5, S32(0)
loc_4a9:
pushtype Pointer ; StackCount = 15
setptr Var15, Var2
setptr Var15, Var15[2]
setptr Var15, Var15[1]
assign Var15, Var5
pop ; StackCount = 14
assign Var5, Var10
pushtype S32 ; StackCount = 15
pushtype Extended ; StackCount = 16
pushtype Double ; StackCount = 17
assign Var17, Arg6
mul Var17, S32(1440)
assign Var16, Var17
pop ; StackCount = 16
pushvar Var15 ; StackCount = 17
call ROUND
pop ; StackCount = 16
pop ; StackCount = 15
sub Var5, Var15
pop ; StackCount = 14
sub Var5, Var12
pushtype BOOLEAN ; StackCount = 15
gt Var15, Var5, Var6
sfz Var15
pop ; StackCount = 14
jf loc_578
assign Var5, Var6
loc_578:
pushtype Pointer ; StackCount = 15
setptr Var15, Var2
setptr Var15, Var15[2]
setptr Var15, Var15[2]
assign Var15, Var5
pop ; StackCount = 14
assign Var5, Var11
pushtype S32 ; StackCount = 15
pushtype Extended ; StackCount = 16
pushtype Double ; StackCount = 17
assign Var17, Arg7
mul Var17, S32(1440)
assign Var16, Var17
pop ; StackCount = 16
pushvar Var15 ; StackCount = 17
call ROUND
pop ; StackCount = 16
pop ; StackCount = 15
sub Var5, Var15
pop ; StackCount = 14
sub Var5, Var13
pushtype BOOLEAN ; StackCount = 15
gt Var15, Var5, Var7
sfz Var15
pop ; StackCount = 14
jf loc_647
assign Var5, Var7
loc_647:
pushtype Pointer ; StackCount = 15
setptr Var15, Var2
setptr Var15, Var15[2]
setptr Var15, Var15[3]
assign Var15, Var5
pop ; StackCount = 14
assign Var2[3], Var2[2]
assign Var2[0], Var3
assign Var2[1], Var3
pushtype S32 ; StackCount = 15
pushtype S32 ; StackCount = 16
assign Var16, S32(-1)
pushtype S32 ; StackCount = 17
assign Var17, S32(0)
pushtype S32 ; StackCount = 18
assign Var18, S32(177)
pushtype S32 ; StackCount = 19
assign Var19, Var4
pushvar Var15 ; StackCount = 20
call SENDMESSAGE
pop ; StackCount = 19
pop ; StackCount = 18
pop ; StackCount = 17
pop ; StackCount = 16
pop ; StackCount = 15
pop ; StackCount = 14
pushtype S32 ; StackCount = 15
pushtype Pointer ; StackCount = 16
setptr Var16, Var2[4]
pushtype S32 ; StackCount = 17
assign Var17, S32(0)
pushtype S32 ; StackCount = 18
assign Var18, S32(1076)
pushtype S32 ; StackCount = 19
assign Var19, Var4
pushvar Var15 ; StackCount = 20
call user32.dll!SendMessageA
pop ; StackCount = 19
pop ; StackCount = 18
pop ; StackCount = 17
pop ; StackCount = 16
pop ; StackCount = 15
pop ; StackCount = 14
assign RetVal, BOOLEAN(1)
pushtype BOOLEAN ; StackCount = 15
loc_787:
pushtype BOOLEAN ; StackCount = 16
pushtype Pointer ; StackCount = 17
setptr Var17, Var2
setptr Var17, Var17[4]
setptr Var17, Var17[0]
pushtype Pointer ; StackCount = 18
setptr Var18, Var2
setptr Var18, Var18[4]
setptr Var18, Var18[1]
lt Var16, Var17, Var18
pop ; StackCount = 17
pop ; StackCount = 16
assign Var15, Var16
pop ; StackCount = 15
jz loc_81d, Var15
and Var15, RetVal
loc_81d:
jz loc_9cf, Var15
pushtype S32 ; StackCount = 16
pushtype U32_2 ; StackCount = 17
assign Var17, Var3
pushvar Var16 ; StackCount = 18
call gdi32.dll!StartPage
pop ; StackCount = 17
pop ; StackCount = 16
gt RetVal, Var16, S32(0)
pop ; StackCount = 15
pushtype BOOLEAN ; StackCount = 16
assign Var16, RetVal
setz Var16
sfz Var16
pop ; StackCount = 15
jf loc_887
jump loc_9cf
loc_887:
pushtype Pointer ; StackCount = 16
setptr Var16, Var2
pushtype S32 ; StackCount = 17
assign Var17, S32(-1)
pushtype S32 ; StackCount = 18
assign Var18, S32(1081)
pushtype S32 ; StackCount = 19
assign Var19, Var4
pushvar Var14 ; StackCount = 20
call user32.dll!SendMessageA_2
pop ; StackCount = 19
pop ; StackCount = 18
pop ; StackCount = 17
pop ; StackCount = 16
pop ; StackCount = 15
pushtype BOOLEAN ; StackCount = 16
pushtype BOOLEAN ; StackCount = 17
pushtype Pointer ; StackCount = 18
setptr Var18, Var2
setptr Var18, Var18[4]
setptr Var18, Var18[0]
le Var17, Var14, Var18
pop ; StackCount = 17
assign Var16, Var17
pop ; StackCount = 16
sfz Var16
pop ; StackCount = 15
jf loc_958
assign RetVal, BOOLEAN(0)
jump loc_9cf
jump loc_9ca
loc_958:
pushtype Pointer ; StackCount = 16
setptr Var16, Var2
setptr Var16, Var16[4]
setptr Var16, Var16[0]
assign Var16, Var14
pop ; StackCount = 15
pushtype S32 ; StackCount = 16
pushtype U32_2 ; StackCount = 17
assign Var17, Var3
pushvar Var16 ; StackCount = 18
call gdi32.dll!EndPage
pop ; StackCount = 17
pop ; StackCount = 16
gt RetVal, Var16, S32(0)
pop ; StackCount = 15
loc_9ca:
jump loc_787
loc_9cf:
pop ; StackCount = 14
pushtype S32 ; StackCount = 15
pushtype S32 ; StackCount = 16
assign Var16, S32(0)
pushtype S32 ; StackCount = 17
assign Var17, S32(0)
pushtype S32 ; StackCount = 18
assign Var18, S32(1081)
pushtype S32 ; StackCount = 19
assign Var19, Var4
pushvar Var15 ; StackCount = 20
call SENDMESSAGE
pop ; StackCount = 19
pop ; StackCount = 18
pop ; StackCount = 17
pop ; StackCount = 16
pop ; StackCount = 15
pop ; StackCount = 14
pushtype BOOLEAN ; StackCount = 15
assign Var15, RetVal
sfz Var15
pop ; StackCount = 14
jf loc_a77
pushtype S32 ; StackCount = 15
pushtype U32_2 ; StackCount = 16
assign Var16, Var3
pushvar Var15 ; StackCount = 17
call gdi32.dll!EndDoc
pop ; StackCount = 16
pop ; StackCount = 15
pop ; StackCount = 14
jump loc_a9a
loc_a77:
pushtype S32 ; StackCount = 15
pushtype U32_2 ; StackCount = 16
assign Var16, Var3
pushvar Var15 ; StackCount = 17
call gdi32.dll!AbortDoc
pop ; StackCount = 16
pop ; StackCount = 15
pop ; StackCount = 14
loc_a9a:
ret
.function(import) external internal returnsval ROUND(__in __unknown)
.function(import) external internal returnsval SENDMESSAGE(__in __unknown,__in __unknown,__in __unknown,__in __unknown)
.function(export) void PRINTBUTTONCLICK(__in TOBJECT Arg1)
pushtype Type30 ; StackCount = 1
pushtype BOOLEAN ; StackCount = 2
pushtype Pointer ; StackCount = 3
setptr Var3, Var1
pushvar Var2 ; StackCount = 4
call SELECTPRINTER
pop ; StackCount = 3
pop ; StackCount = 2
setz Var2
sfz Var2
pop ; StackCount = 1
jf loc_3b
ret
loc_3b:
starteh loc_124, null, null, loc_14d
pushtype BOOLEAN ; StackCount = 2
pushtype Double ; StackCount = 3
assign Var3, Extended(0.50)
pushtype Double ; StackCount = 4
assign Var4, Extended(0.50)
pushtype Double ; StackCount = 5
assign Var5, Extended(0.50)
pushtype Double ; StackCount = 6
assign Var6, Extended(0.50)
pushtype UnicodeString_2 ; StackCount = 7
assign Var7, UnicodeString_3("License")
pushtype TRICHEDITVIEWER ; StackCount = 8
pushtype TWIZARDFORM ; StackCount = 9
pushvar Var9 ; StackCount = 10
call WIZARDFORM
pop ; StackCount = 9
pushvar Var8 ; StackCount = 10
call TWIZARDFORM->LICENSEMEMO
pop ; StackCount = 9
pop ; StackCount = 8
pushtype Type30 ; StackCount = 9
assign Var9, Var1
pushvar Var2 ; StackCount = 10
call PRINTRICHEDIT
pop ; StackCount = 9
pop ; StackCount = 8
pop ; StackCount = 7
pop ; StackCount = 6
pop ; StackCount = 5
pop ; StackCount = 4
pop ; StackCount = 3
pop ; StackCount = 2
pop ; StackCount = 1
endtry
loc_124:
pushtype BOOLEAN ; StackCount = 2
pushtype U32_2 ; StackCount = 3
assign Var3, Var1[4]
pushvar Var2 ; StackCount = 4
call gdi32.dll!DeleteDC
pop ; StackCount = 3
pop ; StackCount = 2
pop ; StackCount = 1
endfinally
loc_14d:
ret
.function(import) external class(TWIZARDFORM, LICENSEMEMO) __pascal void TWIZARDFORM->LICENSEMEMO(__in __unknown,__in __unknown)
.function(export) void ADJUSTPRINTBUTTON()
pushtype BOOLEAN ; StackCount = 1
pushtype TBUTTON ; StackCount = 2
assign Var2, Global0
pushvar Var1 ; StackCount = 3
call !ASSIGNED
pop ; StackCount = 2
pop ; StackCount = 1
sfz Var1
pop ; StackCount = 0
jf loc_138
pushtype S32 ; StackCount = 1
pushtype TRICHEDITVIEWER ; StackCount = 2
pushtype TWIZARDFORM ; StackCount = 3
pushvar Var3 ; StackCount = 4
call WIZARDFORM
pop ; StackCount = 3
pushvar Var2 ; StackCount = 4
call TWIZARDFORM->LICENSEMEMO
pop ; StackCount = 3
pop ; StackCount = 2
pushvar Var1 ; StackCount = 3
call TCONTROL->LEFT
pop ; StackCount = 2
pop ; StackCount = 1
pushtype S32 ; StackCount = 2
pushtype TRICHEDITVIEWER ; StackCount = 3
pushtype TWIZARDFORM ; StackCount = 4
pushvar Var4 ; StackCount = 5
call WIZARDFORM
pop ; StackCount = 4
pushvar Var3 ; StackCount = 5
call TWIZARDFORM->LICENSEMEMO
pop ; StackCount = 4
pop ; StackCount = 3
pushvar Var2 ; StackCount = 4
call TCONTROL->WIDTH
pop ; StackCount = 3
pop ; StackCount = 2
add Var1, Var2
pop ; StackCount = 1
pushtype S32 ; StackCount = 2
pushtype TBUTTON ; StackCount = 3
assign Var3, Global0
pushvar Var2 ; StackCount = 4
call TCONTROL->WIDTH
pop ; StackCount = 3
pop ; StackCount = 2
sub Var1, Var2
pop ; StackCount = 1
pushtype TBUTTON ; StackCount = 2
assign Var2, Global0
call TCONTROL->LEFT_2
pop ; StackCount = 1
pop ; StackCount = 0
pushtype S32 ; StackCount = 1
pushtype TNEWRADIOBUTTON ; StackCount = 2
pushtype TWIZARDFORM ; StackCount = 3
pushvar Var3 ; StackCount = 4
call WIZARDFORM
pop ; StackCount = 3
pushvar Var2 ; StackCount = 4
call TWIZARDFORM->LICENSEACCEPTEDRADIO
pop ; StackCount = 3
pop ; StackCount = 2
pushvar Var1 ; StackCount = 3
call TCONTROL->TOP
pop ; StackCount = 2
pop ; StackCount = 1
pushtype TBUTTON ; StackCount = 2
assign Var2, Global0
call TCONTROL->TOP_2
pop ; StackCount = 1
pop ; StackCount = 0
loc_138:
ret
.function(import) external internal returnsval !ASSIGNED(__in __unknown)
.function(import) external class(TCONTROL, LEFT) __pascal void TCONTROL->LEFT(__in __unknown,__in __unknown)
.function(import) external class(TCONTROL, WIDTH) __pascal void TCONTROL->WIDTH(__in __unknown,__in __unknown)
.function(import) external class(TCONTROL, LEFT, property) __pascal void TCONTROL->LEFT_2(__in __unknown,__in __unknown)
.function(import) external class(TWIZARDFORM, LICENSEACCEPTEDRADIO) __pascal void TWIZARDFORM->LICENSEACCEPTEDRADIO(__in __unknown,__in __unknown)
.function(import) external class(TCONTROL, TOP) __pascal void TCONTROL->TOP(__in __unknown,__in __unknown)
.function(import) external class(TCONTROL, TOP, property) __pascal void TCONTROL->TOP_2(__in __unknown,__in __unknown)
.function(export) void CREATEPRINTBUTTON()
pushtype TCOMPONENT ; StackCount = 1
pushtype TNEWNOTEBOOKPAGE ; StackCount = 2
pushtype TWIZARDFORM ; StackCount = 3
pushvar Var3 ; StackCount = 4
call WIZARDFORM
pop ; StackCount = 3
pushvar Var2 ; StackCount = 4
call TWIZARDFORM->LICENSEPAGE
pop ; StackCount = 3
pop ; StackCount = 2
assign Var1, Var2
pop ; StackCount = 1
pushtype U32_2 ; StackCount = 2
assign Var2, U32_2(29)
pushvar Global0 ; StackCount = 3
call TCONTROL->CREATE
pop ; StackCount = 2
pop ; StackCount = 1
pop ; StackCount = 0
pushtype UnicodeString_2 ; StackCount = 1
assign Var1, UnicodeString_3("&Print")
pushtype TBUTTON ; StackCount = 2
assign Var2, Global0
call TBUTTON->CAPTION
pop ; StackCount = 1
pop ; StackCount = 0
pushtype TNOTIFYEVENT ; StackCount = 1
assign Var1, TNOTIFYEVENT(PRINTBUTTONCLICK)
pushtype TBUTTON ; StackCount = 2
assign Var2, Global0
call TBUTTON->ONCLICK
pop ; StackCount = 1
pop ; StackCount = 0
pushtype TWINCONTROL ; StackCount = 1
pushtype TNEWRADIOBUTTON ; StackCount = 2
pushtype TWIZARDFORM ; StackCount = 3
pushvar Var3 ; StackCount = 4
call WIZARDFORM
pop ; StackCount = 3
pushvar Var2 ; StackCount = 4
call TWIZARDFORM->LICENSEACCEPTEDRADIO
pop ; StackCount = 3
pop ; StackCount = 2
pushvar Var1 ; StackCount = 3
call TCONTROL->PARENT
pop ; StackCount = 2
pop ; StackCount = 1
pushtype TBUTTON ; StackCount = 2
assign Var2, Global0
call TCONTROL->PARENT_2
pop ; StackCount = 1
pop ; StackCount = 0
ret
.function(import) external class(TCONTROL, CREATE) __fastcall returnsval TCONTROL->CREATE(__in __unknown)
.function(import) external class(TWIZARDFORM, LICENSEPAGE) __pascal void TWIZARDFORM->LICENSEPAGE(__in __unknown,__in __unknown)
.function(import) external class(TBUTTON, CAPTION, property) __pascal void TBUTTON->CAPTION(__in __unknown,__in __unknown)
.function(import) external class(TBUTTON, ONCLICK, property) __pascal void TBUTTON->ONCLICK(__in __unknown,__in __unknown)
.function(import) external class(TCONTROL, PARENT) __pascal void TCONTROL->PARENT(__in __unknown,__in __unknown)
.function(import) external class(TCONTROL, PARENT, property) __pascal void TCONTROL->PARENT_2(__in __unknown,__in __unknown)
.function(export) void INITIALIZEWIZARD()
call CREATEPRINTBUTTON
ret
.function(export) void CURPAGECHANGED(__in S32 Arg1)
call ADJUSTPRINTBUTTON
ret
.function(export) BOOLEAN SHOULDSKIPPAGE(__in S32 Arg1)
assign RetVal, BOOLEAN(0)
pushtype BOOLEAN ; StackCount = 1
pushvar Var1 ; StackCount = 2
call ISUPGRADE
pop ; StackCount = 1
sfz Var1
pop ; StackCount = 0
jf loc_90
pushtype BOOLEAN ; StackCount = 1
eq Var1, Arg1, S32(6)
sfz Var1
pop ; StackCount = 0
jf loc_5d
assign RetVal, BOOLEAN(1)
loc_5d:
pushtype BOOLEAN ; StackCount = 1
eq Var1, Arg1, S32(8)
sfz Var1
pop ; StackCount = 0
jf loc_90
assign RetVal, BOOLEAN(1)
loc_90:
ret

View File

@ -39,14 +39,6 @@
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\MSTest.TestFramework.2.2.7\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\MSTest.TestFramework.2.2.7\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Properties\Resources.Designer.cs"> <Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen> <AutoGen>True</AutoGen>
@ -59,6 +51,7 @@
<ItemGroup> <ItemGroup>
<None Include="app.config" /> <None Include="app.config" />
<None Include="CompiledCode.bin" /> <None Include="CompiledCode.bin" />
<None Include="CompiledCode_float80.bin" />
<None Include="CompiledCode_v22.bin" /> <None Include="CompiledCode_v22.bin" />
<None Include="packages.config" /> <None Include="packages.config" />
<None Include="TestIsInsn.bin" /> <None Include="TestIsInsn.bin" />
@ -89,16 +82,20 @@
<ItemGroup> <ItemGroup>
<None Include="TestIsInsn.txt" /> <None Include="TestIsInsn.txt" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<PackageReference Include="MSTest.TestAdapter">
<Version>2.2.7</Version>
</PackageReference>
<PackageReference Include="MSTest.TestFramework">
<Version>2.2.7</Version>
</PackageReference>
<PackageReference Include="NETStandard.Library">
<Version>2.0.3</Version>
</PackageReference>
</ItemGroup>
<ItemGroup>
<Content Include="CompiledCode_float80.txt" />
</ItemGroup>
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" /> <Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\MSTest.TestAdapter.2.2.7\build\net45\MSTest.TestAdapter.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MSTest.TestAdapter.2.2.7\build\net45\MSTest.TestAdapter.props'))" />
<Error Condition="!Exists('..\packages\MSTest.TestAdapter.2.2.7\build\net45\MSTest.TestAdapter.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MSTest.TestAdapter.2.2.7\build\net45\MSTest.TestAdapter.targets'))" />
<Error Condition="!Exists('..\packages\NETStandard.Library.2.0.3\build\netstandard2.0\NETStandard.Library.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\NETStandard.Library.2.0.3\build\netstandard2.0\NETStandard.Library.targets'))" />
</Target>
<Import Project="..\packages\MSTest.TestAdapter.2.2.7\build\net45\MSTest.TestAdapter.targets" Condition="Exists('..\packages\MSTest.TestAdapter.2.2.7\build\net45\MSTest.TestAdapter.targets')" />
<Import Project="..\packages\NETStandard.Library.2.0.3\build\netstandard2.0\NETStandard.Library.targets" Condition="Exists('..\packages\NETStandard.Library.2.0.3\build\netstandard2.0\NETStandard.Library.targets')" />
</Project> </Project>

View File

@ -1,173 +1,212 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <auto-generated> // <auto-generated>
// This code was generated by a tool. // This code was generated by a tool.
// Runtime Version:4.0.30319.42000 // Runtime Version:4.0.30319.42000
// //
// Changes to this file may cause incorrect behavior and will be lost if // Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated. // the code is regenerated.
// </auto-generated> // </auto-generated>
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
namespace IFPSLib.Tests.Properties { namespace IFPSLib.Tests.Properties {
using System; using System;
/// <summary> /// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc. /// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary> /// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder // This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio. // class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen // To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project. // with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources { internal class Resources {
private static global::System.Resources.ResourceManager resourceMan; private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture; private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() { internal Resources() {
} }
/// <summary> /// <summary>
/// Returns the cached ResourceManager instance used by this class. /// Returns the cached ResourceManager instance used by this class.
/// </summary> /// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager { internal static global::System.Resources.ResourceManager ResourceManager {
get { get {
if (object.ReferenceEquals(resourceMan, null)) { if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("IFPSLib.Tests.Properties.Resources", typeof(Resources).Assembly); global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("IFPSLib.Tests.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp; resourceMan = temp;
} }
return resourceMan; return resourceMan;
} }
} }
/// <summary> /// <summary>
/// Overrides the current thread's CurrentUICulture property for all /// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class. /// resource lookups using this strongly typed resource class.
/// </summary> /// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture { internal static global::System.Globalization.CultureInfo Culture {
get { get {
return resourceCulture; return resourceCulture;
} }
set { set {
resourceCulture = value; resourceCulture = value;
} }
} }
/// <summary> /// <summary>
/// Looks up a localized resource of type System.Byte[]. /// Looks up a localized resource of type System.Byte[].
/// </summary> /// </summary>
internal static byte[] CompiledCode { internal static byte[] CompiledCode {
get { get {
object obj = ResourceManager.GetObject("CompiledCode", resourceCulture); object obj = ResourceManager.GetObject("CompiledCode", resourceCulture);
return ((byte[])(obj)); return ((byte[])(obj));
} }
} }
/// <summary> /// <summary>
/// Looks up a localized resource of type System.Byte[]. /// Looks up a localized resource of type System.Byte[].
/// </summary> /// </summary>
internal static byte[] CompiledCode_v22 { internal static byte[] CompiledCode_float80 {
get { get {
object obj = ResourceManager.GetObject("CompiledCode_v22", resourceCulture); object obj = ResourceManager.GetObject("CompiledCode_float80", resourceCulture);
return ((byte[])(obj)); return ((byte[])(obj));
} }
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to .version 23 /// Looks up a localized resource of type System.Byte[].
/// /// </summary>
///.entry !MAIN internal static byte[] CompiledCode_v22 {
/// get {
///.type primitive(Pointer) Pointer object obj = ResourceManager.GetObject("CompiledCode_v22", resourceCulture);
///.type primitive(U32) U32 return ((byte[])(obj));
///.type primitive(Variant) Variant }
///.type primitive(PChar) PChar }
///.type primitive(Currency) Currency
///.type primitive(Extended) Extended /// <summary>
///.type primitive(Double) Double /// Looks up a localized string similar to .version 23
///.type primitive(Single) Single ///
///.type primitive(S64) S64 ///.entry !MAIN
///.type primitive(String) String ///
///.type primitive(U32) U32_2 ///.type primitive(Pointer) Pointer
///.type primitive(S32) S32 ///.type primitive(U32) U32
///.type primitive(S16) S16 ///.type primitive(Variant) Variant
///.type primitive(U16) U16 ///.type primitive(PChar) PChar
///.type primitive(S8) S8 ///.type primitive(Currency) Currency
///.type(export) funcptr(void()) ANY [rest of string was truncated]&quot;;. ///.type primitive(Extended) Extended
/// </summary> ///.type primitive(Double) Double
internal static string CompiledCodeDisasm { ///.type primitive(Single) Single
get { ///.type primitive(S64) S64
return ResourceManager.GetString("CompiledCodeDisasm", resourceCulture); ///.type primitive(String) String
} ///.type primitive(U32) U32_2
} ///.type primitive(S32) S32
///.type primitive(S16) S16
/// <summary> ///.type primitive(U16) U16
/// Looks up a localized string similar to .version 23 ///.type primitive(S8) S8
/// ///.type(export) funcptr(void()) ANY [rest of string was truncated]&quot;;.
///.entry !MAIN /// </summary>
/// internal static string CompiledCodeDisasm {
///.type primitive(Pointer) Pointer get {
///.type primitive(U32) U32 return ResourceManager.GetString("CompiledCodeDisasm", resourceCulture);
///.type primitive(Variant) Variant }
///.type primitive(PChar) PChar }
///.type primitive(Currency) Currency
///.type primitive(Extended) Extended /// <summary>
///.type primitive(Double) Double /// Looks up a localized string similar to .version 23
///.type primitive(Single) Single ///
///.type primitive(S64) S64 ///.entry !MAIN
///.type primitive(String) String ///
///.type primitive(U32) U32_2 ///.type primitive(Pointer) Pointer
///.type primitive(S32) S32 ///.type primitive(U32) U32
///.type primitive(S16) S16 ///.type primitive(Variant) Variant
///.type primitive(U16) U16 ///.type primitive(PChar) PChar
///.type primitive(S8) S8 ///.type primitive(Currency) Currency
///.type(export) funcptr(void()) ANY [rest of string was truncated]&quot;;. ///.type primitive(Extended) Extended
/// </summary> ///.type primitive(Double) Double
internal static string CompiledCodeDisasm_v22 { ///.type primitive(Single) Single
get { ///.type primitive(S64) S64
return ResourceManager.GetString("CompiledCodeDisasm_v22", resourceCulture); ///.type primitive(String) String
} ///.type primitive(U32) U32_2
} ///.type primitive(S32) S32
///.type primitive(S16) S16
/// <summary> ///.type primitive(U16) U16
/// Looks up a localized resource of type System.Byte[]. ///.type primitive(S8) S8
/// </summary> ///.type primitive(String) String_2 /// [rest of string was truncated]&quot;;.
internal static byte[] TestIsInsn { /// </summary>
get { internal static string CompiledCodeDisasm_float80 {
object obj = ResourceManager.GetObject("TestIsInsn", resourceCulture); get {
return ((byte[])(obj)); return ResourceManager.GetString("CompiledCodeDisasm_float80", resourceCulture);
} }
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to .version 23 /// Looks up a localized string similar to .version 22
/// ///
///.type primitive(Pointer) Pointer ///.entry !MAIN
///.type primitive(S32) S32 ///
///.type primitive(U32) U32 ///.type primitive(Pointer) Pointer
///.type primitive(U8) U8 ///.type primitive(U32) U32
/// ///.type primitive(Variant) Variant
///.function(export) U8 INITIALIZEUNINSTALL() ///.type primitive(PChar) PChar
/// pushtype U32 ; StackCount = 1 ///.type primitive(Currency) Currency
/// pushtype U32 ; StackCount = 2 ///.type primitive(Extended) Extended
/// is Var1, Var2, S32 ///.type primitive(Double) Double
/// is Var1, Var2, Var1 ///.type primitive(Single) Single
/// ret ///.type primitive(String) String
/// ///.type primitive(U32) U32_2
/// ///.type primitive(S32) S32
///. ///.type primitive(S16) S16
/// </summary> ///.type primitive(U16) U16
internal static string TestIsInsnDisasm { ///.type primitive(S8) S8
get { ///.type primitive(Char) Char
return ResourceManager.GetString("TestIsInsnDisasm", resourceCulture); ///.type primitive(U32) U32_3
} ///.ty [rest of string was truncated]&quot;;.
} /// </summary>
} internal static string CompiledCodeDisasm_v22 {
} get {
return ResourceManager.GetString("CompiledCodeDisasm_v22", resourceCulture);
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] TestIsInsn {
get {
object obj = ResourceManager.GetObject("TestIsInsn", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized string similar to .version 23
///
///.type primitive(Pointer) Pointer
///.type primitive(S32) S32
///.type primitive(U32) U32
///.type primitive(U8) U8
///
///.function(export) U8 INITIALIZEUNINSTALL()
/// pushtype U32 ; StackCount = 1
/// pushtype U32 ; StackCount = 2
/// is Var1, Var2, S32
/// is Var1, Var2, Var1
/// ret
///
///
///.
/// </summary>
internal static string TestIsInsnDisasm {
get {
return ResourceManager.GetString("TestIsInsnDisasm", resourceCulture);
}
}
}
}

View File

@ -124,9 +124,15 @@
<data name="CompiledCodeDisasm" type="System.Resources.ResXFileRef, System.Windows.Forms"> <data name="CompiledCodeDisasm" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\CompiledCode.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value> <value>..\CompiledCode.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
</data> </data>
<data name="CompiledCodeDisasm_float80" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\CompiledCode_float80.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
</data>
<data name="CompiledCodeDisasm_v22" type="System.Resources.ResXFileRef, System.Windows.Forms"> <data name="CompiledCodeDisasm_v22" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\CompiledCode_v22.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value> <value>..\CompiledCode_v22.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
</data> </data>
<data name="CompiledCode_float80" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\CompiledCode_float80.bin;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="CompiledCode_v22" type="System.Resources.ResXFileRef, System.Windows.Forms"> <data name="CompiledCode_v22" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\CompiledCode_v22.bin;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>..\CompiledCode_v22.bin;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data> </data>

View File

@ -79,5 +79,17 @@ namespace IFPSLib.Tests
{ {
TestAsmImpl(Resources.TestIsInsnDisasm, Resources.TestIsInsn); TestAsmImpl(Resources.TestIsInsnDisasm, Resources.TestIsInsn);
} }
[TestMethod]
public void TestLoadSaveFloat80()
{
TestLoadSaveImpl(Resources.CompiledCode_float80);
}
[TestMethod]
public void TestAsmFloat80()
{
TestAsmImpl(Resources.CompiledCodeDisasm_float80, Resources.CompiledCode_float80);
}
} }
} }

View File

@ -148,7 +148,12 @@ namespace IFPSLib.Emit
{ {
var isVoid = ReturnArgument == null; var isVoid = ReturnArgument == null;
var ret = ArgumentVariable.Create(index + (isVoid ? 0 : 1), isVoid); var ret = ArgumentVariable.Create(index + (isVoid ? 0 : 1), isVoid);
ret.Name = Arguments[index].Name; if (!Exported)
{
if (!isVoid && index == 0) ret.Name = "RetVal";
else ret.Name = string.Format("Arg{0}", index + (isVoid ? 0 : 1));
}
else ret.Name = Arguments[index].Name;
return ret; return ret;
} }

View File

@ -8,6 +8,7 @@ using SharpFloat.FloatingPoint;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Collections; using System.Collections;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Globalization;
namespace IFPSLib namespace IFPSLib
{ {
@ -16,6 +17,7 @@ namespace IFPSLib
/// </summary> /// </summary>
public class TypedData public class TypedData
{ {
private static readonly CultureInfo s_Culture = new CultureInfo("en");
public IType Type { get; } public IType Type { get; }
public object Value { get; } public object Value { get; }
@ -128,11 +130,11 @@ namespace IFPSLib
return new TypedData(type, br.Read<double>()); return new TypedData(type, br.Read<double>());
case PascalTypeCode.Extended: case PascalTypeCode.Extended:
{ {
// BUGBUG: there must be something beter than this... but for now, it'll do // BUGBUG: there must be something better than this... but for now, it'll do
var sb = new StringBuilder(); var sb = new StringBuilder();
ExtF80.PrintFloat80(sb, br.Read<ExtF80>(), PrintFloatFormat.ScientificFormat, 19); ExtF80.PrintFloat80(sb, br.Read<ExtF80>(), PrintFloatFormat.ScientificFormat, 19);
TrimDecimalString(sb); TrimDecimalString(sb);
return new TypedData(type, decimal.Parse(sb.ToString(), System.Globalization.NumberStyles.Float)); return new TypedData(type, decimal.Parse(sb.ToString(), NumberStyles.Float, s_Culture));
} }
case PascalTypeCode.Currency: case PascalTypeCode.Currency:
@ -207,7 +209,7 @@ namespace IFPSLib
WriteValue<double>(bw); WriteValue<double>(bw);
break; break;
case PascalTypeCode.Extended: case PascalTypeCode.Extended:
if (!ExtF80.TryParse(ValueAs<decimal>().ToString(), out var extf)) if (!ExtF80.TryParse(ValueAs<decimal>().ToString(s_Culture), out var extf))
throw new ArgumentOutOfRangeException("Value {0} cannot fit into an 80-bit floating point number"); throw new ArgumentOutOfRangeException("Value {0} cannot fit into an 80-bit floating point number");
bw.Write(extf); bw.Write(extf);
break; break;
@ -342,7 +344,7 @@ namespace IFPSLib
sb.Append(')'); sb.Append(')');
return sb.ToString(); return sb.ToString();
} }
return string.Format("{0}({1})", Type.Name, Value); return string.Format(s_Culture, "{0}({1})", Type.Name, Value);
} }
} }
} }

View File

@ -8,30 +8,49 @@ using Parsing;
namespace Driver { namespace Driver {
public class Compiler { public class Compiler {
private static readonly bool SHOW_TIME = false;
private static System.Diagnostics.Stopwatch StartTimer()
{
var watch = new System.Diagnostics.Stopwatch();
watch.Start();
return watch;
}
private Compiler(String source) { private Compiler(String source) {
this.Source = source; this.Source = source;
// Lexical analysis // Lexical analysis
var watch = StartTimer();
Scanner scanner = new Scanner(source); Scanner scanner = new Scanner(source);
this.Tokens = scanner.Tokens.ToImmutableList(); this.Tokens = scanner.Tokens.ToImmutableList();
watch.Stop();
if (SHOW_TIME) Console.WriteLine("lexer: {0} ms", watch.ElapsedMilliseconds);
// Parse // Parse
watch = StartTimer();
var parserResult = CParsers.Parse(this.Tokens); var parserResult = CParsers.Parse(this.Tokens);
watch.Stop();
if (SHOW_TIME) Console.WriteLine("parser: {0} ms", watch.ElapsedMilliseconds);
if (!parserResult.IsSuccessful || parserResult.Source.Count() != 1) { if (!parserResult.IsSuccessful || parserResult.Source.Count() != 1) {
throw new InvalidOperationException($"Parsing error:\n{parserResult}"); throw new InvalidOperationException($"Parsing error:\n{parserResult}");
} }
this.SyntaxTree = parserResult.Result; this.SyntaxTree = parserResult.Result;
// Semantic analysis // Semantic analysis
watch = StartTimer();
var semantReturn = this.SyntaxTree.GetTranslnUnit(); var semantReturn = this.SyntaxTree.GetTranslnUnit();
watch.Stop();
if (SHOW_TIME) Console.WriteLine("semant: {0} ms", watch.ElapsedMilliseconds);
this.AbstractSyntaxTree = semantReturn.Value; this.AbstractSyntaxTree = semantReturn.Value;
this.Environment = semantReturn.Env; this.Environment = semantReturn.Env;
// Code generation // Code generation
watch = StartTimer();
var state = new CGenState(); var state = new CGenState();
this.AbstractSyntaxTree.CodeGenerate(state); this.AbstractSyntaxTree.CodeGenerate(state);
state.EmitCallsToCtor(); state.EmitCallsToCtor();
this.Script = state.Script; this.Script = state.Script;
watch.Stop();
if (SHOW_TIME) Console.WriteLine("codegen: {0} ms", watch.ElapsedMilliseconds);
} }
public static Compiler FromSource(String src) { public static Compiler FromSource(String src) {

View File

@ -7,8 +7,10 @@ using static Parsing.ParserCombinator;
using System.Collections.Immutable; using System.Collections.Immutable;
namespace Parsing { namespace Parsing {
public partial class CParsers { public partial class CParsers
static CParsers() { {
static CParsers()
{
SetExpressionRules(); SetExpressionRules();
SetDeclarationRules(); SetDeclarationRules();
SetExternalDefinitionRules(); SetExternalDefinitionRules();
@ -18,44 +20,56 @@ namespace Parsing {
public static IParserResult<TranslnUnit> Parse(IEnumerable<Token> tokens) => public static IParserResult<TranslnUnit> Parse(IEnumerable<Token> tokens) =>
TranslationUnit.Parse(new ParserInput(new ParserEnvironment(), tokens)); TranslationUnit.Parse(new ParserInput(new ParserEnvironment(), tokens));
public class ConstCharParser : IParser<Expr> { public class ConstCharParser : IParser<Expr>
{
public RuleCombining Combining => RuleCombining.NONE; public RuleCombining Combining => RuleCombining.NONE;
public IParserResult<Expr> Parse(ParserInput input) { public IParserResult<Expr> Parse(ParserInput input)
{
var token = input.Source.First() as TokenCharConst; var token = input.Source.First() as TokenCharConst;
if (token == null) { if (token == null)
{
return new ParserFailed<Expr>(input); return new ParserFailed<Expr>(input);
} }
return ParserSucceeded.Create(new IntLiteral(token.Value, TokenInt.IntSuffix.NONE), input.Environment, input.Source.Skip(1)); return ParserSucceeded.Create(new IntLiteral(token.Value, TokenInt.IntSuffix.NONE), input.Environment, input.Source.Skip(1));
} }
} }
public class ConstIntParser : IParser<Expr> { public class ConstIntParser : IParser<Expr>
{
public RuleCombining Combining => RuleCombining.NONE; public RuleCombining Combining => RuleCombining.NONE;
public IParserResult<Expr> Parse(ParserInput input) { public IParserResult<Expr> Parse(ParserInput input)
{
var token = input.Source.First() as TokenInt; var token = input.Source.First() as TokenInt;
if (token == null) { if (token == null)
{
return new ParserFailed<Expr>(input); return new ParserFailed<Expr>(input);
} }
return ParserSucceeded.Create(new IntLiteral(token.Val, token.Suffix), input.Environment, input.Source.Skip(1)); return ParserSucceeded.Create(new IntLiteral(token.Val, token.Suffix), input.Environment, input.Source.Skip(1));
} }
} }
public class ConstFloatParser : IParser<Expr> { public class ConstFloatParser : IParser<Expr>
{
public RuleCombining Combining => RuleCombining.NONE; public RuleCombining Combining => RuleCombining.NONE;
public IParserResult<Expr> Parse(ParserInput input) { public IParserResult<Expr> Parse(ParserInput input)
{
var token = input.Source.First() as TokenFloat; var token = input.Source.First() as TokenFloat;
if (token == null) { if (token == null)
{
return new ParserFailed<Expr>(input); return new ParserFailed<Expr>(input);
} }
return ParserSucceeded.Create(new FloatLiteral(token.Value, token.Suffix), input.Environment, input.Source.Skip(1)); return ParserSucceeded.Create(new FloatLiteral(token.Value, token.Suffix), input.Environment, input.Source.Skip(1));
} }
} }
public class StringLiteralParser : IParser<Expr> { public class StringLiteralParser : IParser<Expr>
{
public RuleCombining Combining => RuleCombining.NONE; public RuleCombining Combining => RuleCombining.NONE;
public IParserResult<Expr> Parse(ParserInput input) { public IParserResult<Expr> Parse(ParserInput input)
{
var token = input.Source.First() as TokenString; var token = input.Source.First() as TokenString;
if (token == null) { if (token == null)
{
return new ParserFailed<Expr>(input); return new ParserFailed<Expr>(input);
} }
return ParserSucceeded.Create(new StringLiteral(token.Val), input.Environment, input.Source.Skip(1)); return ParserSucceeded.Create(new StringLiteral(token.Val), input.Environment, input.Source.Skip(1));
@ -76,8 +90,10 @@ namespace Parsing {
} }
} }
public class BinaryOperatorBuilder { public class BinaryOperatorBuilder
public BinaryOperatorBuilder(IConsumer operatorConsumer, Func<Expr, Expr, Expr> nodeCreator) { {
public BinaryOperatorBuilder(IConsumer operatorConsumer, Func<Expr, Expr, Expr> nodeCreator)
{
this.OperatorConsumer = operatorConsumer; this.OperatorConsumer = operatorConsumer;
this.NodeCreator = nodeCreator; this.NodeCreator = nodeCreator;
} }
@ -89,29 +105,93 @@ namespace Parsing {
public Func<Expr, Expr, Expr> NodeCreator { get; } public Func<Expr, Expr, Expr> NodeCreator { get; }
} }
// TODO: create a dedicated class for this. public class OperatorParser : IParser<Expr>
public static IParser<Expr> BinaryOperator(IParser<Expr> operandParser, params BinaryOperatorBuilder[] builders) { {
ImmutableList<ITransformer<Expr, Expr>> transformers = builders.Select(builder => private IParser<Expr> lhsParser;
Given<Expr>() private IParser<Expr> rhsParser;
.Then(builder.OperatorConsumer) private readonly ImmutableList<BinaryOperatorBuilder> builders;
.Then(operandParser) private readonly bool needsOne;
.Then(builder.NodeCreator)
).ToImmutableList(); public OperatorParser(IParser<Expr> operandParser, IEnumerable<BinaryOperatorBuilder> builders) : this(operandParser, operandParser, builders)
return operandParser.Then((new OrTransformer<Expr, Expr>(transformers)).ZeroOrMore()); {
needsOne = false;
}
public OperatorParser(IParser<Expr> lhsParser, IParser<Expr> rhsParser, IEnumerable<BinaryOperatorBuilder> builders)
{
this.lhsParser = lhsParser;
this.rhsParser = rhsParser;
this.builders = builders.ToImmutableList();
needsOne = true;
}
public RuleCombining Combining => RuleCombining.THEN;
public IParserResult<Expr> Parse(ParserInput input)
{
var firstResult = lhsParser.Parse(input);
if (!firstResult.IsSuccessful)
{
return new ParserFailed<Expr>(firstResult);
}
return Transform(firstResult.Result, firstResult.ToInput());
}
private IParserResult<Expr> TransformImpl(Expr seed, ParserInput input)
{
List<IParserFailed> failed = new List<IParserFailed>();
foreach (var builder in builders) {
var given = ParserSucceeded.Create(seed, input.Environment, input.Source);
var result1 = builder.OperatorConsumer.Consume(given.ToInput());
if (!result1.IsSuccessful)
{
failed.Add(new ParserFailed<Expr>(result1));
continue;
}
var result2 = rhsParser.Parse(result1.ToInput());
if (!result2.IsSuccessful)
{
failed.Add(new ParserFailed<Expr>(result2));
continue;
}
var transform = builder.NodeCreator(seed, result2.Result);
var ret = ParserSucceeded.Create(transform, result2.Environment, result2.Source);
var expr = transform as IStoredLineInfo;
if (expr != null)
{
expr.Copy(ret);
}
return ret;
}
return new ParserFailed<Expr>(input, failed);
}
public IParserResult<Expr> Transform(Expr seed, ParserInput input)
{
IParserResult<Expr> curResult = needsOne ? TransformImpl(seed, input) : ParserSucceeded.Create(seed, input.Environment, input.Source);
if (!curResult.IsSuccessful) return new ParserFailed<Expr>(curResult);
IParserResult<Expr> lastSuccessfulResult;
do
{
lastSuccessfulResult = curResult;
curResult = TransformImpl(lastSuccessfulResult.Result, lastSuccessfulResult.ToInput());
} while (curResult.IsSuccessful);
return lastSuccessfulResult;
}
} }
public static IParser<Expr> BinaryOperator(IParser<Expr> operandParser, params BinaryOperatorBuilder[] builders)
=> new OperatorParser(operandParser, builders);
public static IParser<Expr> AssignmentOperator( public static IParser<Expr> AssignmentOperator(
IParser<Expr> lhsParser, IParser<Expr> lhsParser,
IParser<Expr> rhsParser, IParser<Expr> rhsParser,
params BinaryOperatorBuilder[] builders params BinaryOperatorBuilder[] builders
) { ) => new OperatorParser(lhsParser, rhsParser, builders);
var transformers = builders.Select(builder =>
Given<Expr>()
.Then(builder.OperatorConsumer)
.Then(rhsParser)
.Then(builder.NodeCreator)
).ToImmutableList();
return lhsParser.Then((new OrTransformer<Expr, Expr>(transformers)).OneOrMore());
}
} }
} }

View File

@ -1,4 +1,5 @@
using System; using System;
using System.Text;
namespace LexicalAnalysis { namespace LexicalAnalysis {
/// <summary> /// <summary>
@ -61,7 +62,7 @@ namespace LexicalAnalysis {
} }
private State _state; private State _state;
private String _scanned; private StringBuilder _scanned;
// quote : Char // quote : Char
// ============ // ============
@ -71,11 +72,11 @@ namespace LexicalAnalysis {
public FSAChar(Char quote) { public FSAChar(Char quote) {
this._state = State.START; this._state = State.START;
this._quote = quote; this._quote = quote;
this._scanned = ""; this._scanned = new StringBuilder();
} }
public override void Reset() { public override void Reset() {
this._scanned = ""; this._scanned.Clear();
this._state = State.START; this._state = State.START;
} }
@ -106,7 +107,7 @@ namespace LexicalAnalysis {
// ========================== // ==========================
// //
public String RetrieveRaw() { public String RetrieveRaw() {
return this._scanned.Substring(0, this._scanned.Length - 1); return this._scanned.ToString(0, this._scanned.Length - 1);
} }
// RetrieveChar : () -> Char // RetrieveChar : () -> Char
@ -157,7 +158,7 @@ namespace LexicalAnalysis {
// Implementation of the FSA // Implementation of the FSA
// //
public override void ReadChar(Char ch) { public override void ReadChar(Char ch) {
this._scanned = this._scanned + ch; this._scanned = this._scanned.Append(ch);
switch (this._state) { switch (this._state) {
case State.END: case State.END:
case State.ERROR: case State.ERROR:
@ -230,7 +231,7 @@ namespace LexicalAnalysis {
// ================== // ==================
// //
public override void ReadEOF() { public override void ReadEOF() {
this._scanned = this._scanned + '0'; this._scanned = this._scanned.Append('0');
switch (this._state) { switch (this._state) {
case State.C: case State.C:
case State.SO: case State.SO:

View File

@ -1,4 +1,5 @@
using System; using System;
using System.Text;
namespace LexicalAnalysis { namespace LexicalAnalysis {
/// <summary> /// <summary>
@ -60,7 +61,7 @@ namespace LexicalAnalysis {
DPL DPL
}; };
private String _raw; private StringBuilder _raw;
private Int64 _intPart; private Int64 _intPart;
private Int64 _fracPart; private Int64 _fracPart;
private Int64 _fracCount; private Int64 _fracCount;
@ -77,7 +78,7 @@ namespace LexicalAnalysis {
this._expPart = 0; this._expPart = 0;
this._suffix = TokenFloat.FloatSuffix.NONE; this._suffix = TokenFloat.FloatSuffix.NONE;
this._expPos = true; this._expPos = true;
this._raw = ""; this._raw = new StringBuilder();
} }
public override void Reset() { public override void Reset() {
@ -88,7 +89,7 @@ namespace LexicalAnalysis {
this._expPart = 0; this._expPart = 0;
this._suffix = TokenFloat.FloatSuffix.NONE; this._suffix = TokenFloat.FloatSuffix.NONE;
this._expPos = true; this._expPos = true;
this._raw = ""; this._raw.Clear();
} }
public override FSAStatus GetStatus() { public override FSAStatus GetStatus() {
@ -111,11 +112,11 @@ namespace LexicalAnalysis {
} else { } else {
val = (this._intPart + this._fracPart * Math.Pow(0.1, this._fracCount)) * Math.Pow(10, -this._expPart); val = (this._intPart + this._fracPart * Math.Pow(0.1, this._fracCount)) * Math.Pow(10, -this._expPart);
} }
return new TokenFloat(val, this._suffix, this._raw.Substring(0, this._raw.Length - 1)); return new TokenFloat(val, this._suffix, this._raw.ToString(0, this._raw.Length - 1));
} }
public override void ReadChar(Char ch) { public override void ReadChar(Char ch) {
this._raw += ch; this._raw.Append(ch);
switch (this._state) { switch (this._state) {
case State.ERROR: case State.ERROR:
case State.END: case State.END:

View File

@ -1,4 +1,6 @@
using System; using System;
using System.Linq;
using System.Text;
namespace LexicalAnalysis { namespace LexicalAnalysis {
/// <summary> /// <summary>
@ -24,16 +26,16 @@ namespace LexicalAnalysis {
ID ID
}; };
private State _state; private State _state;
private String _scanned; private StringBuilder _scanned;
public FSAIdentifier() { public FSAIdentifier() {
this._state = State.START; this._state = State.START;
this._scanned = ""; this._scanned = new StringBuilder();
} }
public override void Reset() { public override void Reset() {
this._state = State.START; this._state = State.START;
this._scanned = ""; this._scanned.Clear();
} }
public override FSAStatus GetStatus() { public override FSAStatus GetStatus() {
@ -50,7 +52,7 @@ namespace LexicalAnalysis {
} }
public override Token RetrieveToken() { public override Token RetrieveToken() {
String name = this._scanned.Substring(0, this._scanned.Length - 1); String name = this._scanned.ToString(0, this._scanned.Length - 1);
if (TokenKeyword.Keywords.ContainsKey(name)) { if (TokenKeyword.Keywords.ContainsKey(name)) {
return new TokenKeyword(TokenKeyword.Keywords[name]); return new TokenKeyword(TokenKeyword.Keywords[name]);
} }
@ -58,7 +60,7 @@ namespace LexicalAnalysis {
} }
public override void ReadChar(Char ch) { public override void ReadChar(Char ch) {
this._scanned = this._scanned + ch; this._scanned = this._scanned.Append(ch);
switch (this._state) { switch (this._state) {
case State.END: case State.END:
case State.ERROR: case State.ERROR:
@ -82,7 +84,7 @@ namespace LexicalAnalysis {
} }
public override void ReadEOF() { public override void ReadEOF() {
this._scanned = this._scanned + '0'; this._scanned = this._scanned.Append('0');
switch (this._state) { switch (this._state) {
case State.ID: case State.ID:
this._state = State.END; this._state = State.END;

View File

@ -1,4 +1,5 @@
using System; using System;
using System.Text;
namespace LexicalAnalysis { namespace LexicalAnalysis {
/// <summary> /// <summary>
@ -69,21 +70,21 @@ namespace LexicalAnalysis {
}; };
private Int64 _val; private Int64 _val;
private String _raw; private StringBuilder _raw;
private TokenInt.IntSuffix _suffix; private TokenInt.IntSuffix _suffix;
private State _state; private State _state;
public FSAInt() { public FSAInt() {
this._state = State.START; this._state = State.START;
this._val = 0; this._val = 0;
this._raw = ""; this._raw = new StringBuilder();
this._suffix = TokenInt.IntSuffix.NONE; this._suffix = TokenInt.IntSuffix.NONE;
} }
public override void Reset() { public override void Reset() {
this._state = State.START; this._state = State.START;
this._val = 0; this._val = 0;
this._raw = ""; this._raw.Clear();
this._suffix = TokenInt.IntSuffix.NONE; this._suffix = TokenInt.IntSuffix.NONE;
} }
@ -101,11 +102,11 @@ namespace LexicalAnalysis {
} }
public override Token RetrieveToken() { public override Token RetrieveToken() {
return new TokenInt(this._val, this._suffix, this._raw.Substring(0, this._raw.Length - 1)); return new TokenInt(this._val, this._suffix, this._raw.ToString(0, this._raw.Length - 1));
} }
public override void ReadChar(Char ch) { public override void ReadChar(Char ch) {
this._raw += ch; this._raw.Append(ch);
switch (this._state) { switch (this._state) {
case State.ERROR: case State.ERROR:
case State.END: case State.END:

View File

@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Linq; using System.Linq;
using System.Text;
namespace LexicalAnalysis { namespace LexicalAnalysis {
/// <summary> /// <summary>
@ -166,16 +167,16 @@ namespace LexicalAnalysis {
); );
private State _state; private State _state;
private String _scanned; private StringBuilder _scanned;
public FSAOperator() { public FSAOperator() {
this._state = State.START; this._state = State.START;
this._scanned = ""; this._scanned = new StringBuilder();
} }
public override sealed void Reset() { public override sealed void Reset() {
this._state = State.START; this._state = State.START;
this._scanned = ""; this._scanned.Clear();
} }
public override sealed FSAStatus GetStatus() { public override sealed FSAStatus GetStatus() {
@ -192,11 +193,11 @@ namespace LexicalAnalysis {
} }
public override sealed Token RetrieveToken() { public override sealed Token RetrieveToken() {
return new TokenOperator(TokenOperator.Operators[this._scanned.Substring(0, this._scanned.Length - 1)]); return new TokenOperator(TokenOperator.Operators[this._scanned.ToString(0, this._scanned.Length - 1)]);
} }
public override sealed void ReadChar(Char ch) { public override sealed void ReadChar(Char ch) {
this._scanned = this._scanned + ch; this._scanned = this._scanned.Append(ch);
switch (this._state) { switch (this._state) {
case State.END: case State.END:
case State.ERROR: case State.ERROR:
@ -386,7 +387,7 @@ namespace LexicalAnalysis {
} }
public override sealed void ReadEOF() { public override sealed void ReadEOF() {
this._scanned = this._scanned + '0'; this._scanned = this._scanned.Append('0');
switch (this._state) { switch (this._state) {
case State.FINISH: case State.FINISH:
case State.SUB: case State.SUB:

View File

@ -36,21 +36,31 @@ namespace LexicalAnalysis {
private IEnumerable<Token> Lex() { private IEnumerable<Token> Lex() {
var tokens = new List<Token>(); var tokens = new List<Token>();
int line = 1, column = 1, lastColumn = column; int line = 1, column = 1, lastColumn = column;
char lastChr = '\0';
for (Int32 i = 0; i < this.Source.Length; ++i) { for (Int32 i = 0; i < this.Source.Length; ++i) {
if (i > 0 && this.Source[i - 1] == '\n') if (lastChr == '\n')
{ {
line++; line++;
lastColumn = 1; lastColumn = 1;
column = 1; column = 1;
} }
else column++; else column++;
this.FSAs.ForEach(fsa => fsa.ReadChar(this.Source[i])); bool isRunning = false;
int endIdx = -1;
var chr = Source[i];
for (int fsaIdx = 0; fsaIdx < FSAs.Count; fsaIdx++)
{
var fsa = FSAs[fsaIdx];
fsa.ReadChar(chr);
var status = fsa.GetStatus();
if (status == FSAStatus.RUNNING) isRunning = true;
else if (endIdx == -1 && status == FSAStatus.END) endIdx = fsaIdx;
}
// if no running // if no running
if (this.FSAs.FindIndex(fsa => fsa.GetStatus() == FSAStatus.RUNNING) == -1) { if (!isRunning) {
Int32 idx = this.FSAs.FindIndex(fsa => fsa.GetStatus() == FSAStatus.END); if (endIdx != -1) {
if (idx != -1) { Token token = this.FSAs[endIdx].RetrieveToken();
Token token = this.FSAs[idx].RetrieveToken();
if (token.Kind != TokenKind.NONE) { if (token.Kind != TokenKind.NONE) {
token.Line = line; token.Line = line;
token.Column = lastColumn; token.Column = lastColumn;
@ -58,19 +68,26 @@ namespace LexicalAnalysis {
tokens.Add(token); tokens.Add(token);
} }
i--; column--; i--; column--;
if (this.Source[i] == '\n') line--; if (lastChr == '\n') line--;
this.FSAs.ForEach(fsa => fsa.Reset()); foreach (var fsa in FSAs) fsa.Reset();
} else { } else {
Console.WriteLine("error"); Console.WriteLine("error");
} }
} }
if (!isRunning || endIdx == -1) lastChr = chr;
} }
this.FSAs.ForEach(fsa => fsa.ReadEOF()); var endIdx2 = -1;
for (int fsaIdx = 0; fsaIdx < FSAs.Count; fsaIdx++)
{
var fsa = FSAs[fsaIdx];
fsa.ReadEOF();
if (endIdx2 != -1) continue;
if (fsa.GetStatus() == FSAStatus.END) endIdx2 = fsaIdx;
}
// find END // find END
Int32 idx2 = this.FSAs.FindIndex(fsa => fsa.GetStatus() == FSAStatus.END); if (endIdx2 != -1) {
if (idx2 != -1) { Token token = this.FSAs[endIdx2].RetrieveToken();
Token token = this.FSAs[idx2].RetrieveToken();
if (token.Kind != TokenKind.NONE) { if (token.Kind != TokenKind.NONE) {
token.Line = line; token.Line = line;
token.Column = column + 1; token.Column = column + 1;

View File

@ -1,4 +1,5 @@
using System; using System;
using System.Text;
namespace LexicalAnalysis { namespace LexicalAnalysis {
/// <summary> /// <summary>
@ -54,22 +55,22 @@ namespace LexicalAnalysis {
private State _state; private State _state;
private readonly FSAChar _fsachar; private readonly FSAChar _fsachar;
private String _val; private StringBuilder _val;
private String _raw; private StringBuilder _raw;
private bool unicode = false; private bool unicode = false;
public FSAString() { public FSAString() {
this._state = State.START; this._state = State.START;
this._fsachar = new FSAChar('\"'); this._fsachar = new FSAChar('\"');
this._raw = ""; this._raw = new StringBuilder();
this._val = ""; this._val = new StringBuilder();
} }
public override void Reset() { public override void Reset() {
this._state = State.START; this._state = State.START;
this._fsachar.Reset(); this._fsachar.Reset();
this._raw = ""; this._raw.Clear();
this._val = ""; this._val.Clear();
unicode = false; unicode = false;
} }
@ -87,8 +88,8 @@ namespace LexicalAnalysis {
} }
public override Token RetrieveToken() { public override Token RetrieveToken() {
if (unicode) return new TokenUnicodeString(this._val, this._raw); if (unicode) return new TokenUnicodeString(this._val.ToString(), this._raw.ToString());
return new TokenString(this._val, this._raw); return new TokenString(this._val.ToString(), this._raw.ToString());
} }
public override void ReadChar(Char ch) { public override void ReadChar(Char ch) {
@ -129,8 +130,8 @@ namespace LexicalAnalysis {
switch (this._fsachar.GetStatus()) { switch (this._fsachar.GetStatus()) {
case FSAStatus.END: case FSAStatus.END:
this._state = State.Q; this._state = State.Q;
this._val = this._val + this._fsachar.RetrieveChar(); this._val.Append(this._fsachar.RetrieveChar());
this._raw = this._raw + this._fsachar.RetrieveRaw(); this._raw.Append(this._fsachar.RetrieveRaw());
this._fsachar.Reset(); this._fsachar.Reset();
ReadChar(ch); ReadChar(ch);
break; break;