Closed 3FLLC closed 1 year ago
const
_a:string='abc';
var
a:string;
begin
a:=_a;
writeln(a);
writeln(length(a));
writeln(_a);
writeln(_a[1]);
writeln(a[1]);
end.
last writeln fails - where should I look?
@nielsAD Cannot invoke identifier at line 13, column 13 in file "t.p"
Once I have a ballpark of where to look, I can diff the source. oddly, my old code runs it perfectly, so this is where something I used to do, does not marry-up with the way it should be done now.
See tests for (1) autoproperties, (2) constaddress (allows pointers to constants), (3) compound operators.
As for the index operation; probably the result type is lost somewhere.
The code you pasted above works for me (RangeChecking is turned on by default). Maybe check if you made any modifications to handling lcoRangeCheck
.
works:
{$R-}
const
_a:string='abc';
var
a:string;
begin
a:=_a;
writeln(a);
writeln(length(a));
writeln(_a);
writeln(_a[1]);
writeln(a[1]);
end.
however, what if I need to turn off range checking for one routine and then back on for another? In my tests, I see compiler options are global not local to the routines. e.g. the last state of $R is the state used for the whole run-time. Is this fixable?
@nielsAD MP-Lape is now manually synchronized all .pas files.
To-Do:
initialization
Lape_InitKeywordsCache();
{$IFDEF LoadDefaultFormatSettings}
GetLocaleFormatSettings(0, FormatSettings);
{$ENDIF}
finalization
Lape_ClearKeywordsCache();
making it thread safe).
however, what if I need to turn off range checking for one routine and then back on for another? In my tests, I see compiler options are global not local to the routines. e.g. the last state of $R is the state used for the whole run-time. Is this fixable? - 3FLLC
The switch does not affect the whole script but only from the point where it's toggled, and until it's changed again, switches are parsed as we go.
This should display it:
var
a:array of Int32;
begin
{$R-}
a[10]; //passes by
{$R+}
try
a[10]; //raises
except
WriteLn 'raised';
end;
{$R-} //the rest of the code uses R- now.
a[10]; //passes by
end.
so for your function, you enable it in the begining, and then disable it at the end.
Your are right, I introduced the bug :-(
fixing property Options:{...} read FOptions write FBaseOptions; (making it use SetOptions) ended breaking FOptions' scope. Undoing my "fix" and just applying "Compiler.Reset()" everywhere I need the change to happen pre Compiler.compile(...).
Thanks!!
Undid my setOptions() change to lpvartypes (compiler base), and I still get:
Compilation error: "Cannot invoke identifier at line 13, column 6
@WarPie - thanks for proven it did work - after doing a line by line comparison - I finally found, _RangeCheck was my issue. It was not migrated into MP2, as I thought it was like Between(..) or inRange(...) from my Math RTL. Once I found vartypes_array uses _RangeCheck I was able to resolve it. PHEW!
@nielsAD new question - I am porting over some UUID/MSGID code from C to MP.... how hard would it be for us to implement "bit" support in records?
struct
{
unsigned TaskNumber:5;
unsigned DayOfYear:9;
unsigned Year:2; /* Enough to meet the three-year rule */
unsigned Secs30:12;
unsigned Count:4;
} x; // sizeof() == 32
Or is there a way to have LA-PE align to this structure?
The best way to work around this is by just using a 32 bit integer type and wrapping the C fields into getters/setters.
Adding this to Lape is possible but difficult, because there's nothing like it at the moment. Currently, there's no read
evaluation, which would be needed for something like this. Adding that is non-trivial, but would also be beneficial for properties.
@nielsAD a while back you helped me implement this, but I cannot find my notes.
Write(#27+']2;LiveMenu - Telnet Edition'+#7);
ctlcms.init(nil);
ctlcms.setFilename(rootpath+'control.cms');
ctlcms.setFirstlineIsSchema(false);
ctlcms.open();
ds:=ctlcms;
df:=ds.FieldByName('Field1');
_Version:=df.getAsFloat;
ctlcms.free;
Note I have to store TField to DF then I can work with DF.getAsFloat. You had pointed me to the piece of code to understand ds.FieldByName("Field1").getAsFloat --- right now if I run that statement I get "Variable expected at line..." so I have to store the object to variable, then reference that variable/object to get to it's methods. ... do you recall what I need to expand out?? (I still have my pre-LAPE-MERGE code, so I will be able to cut-n-paste my patch, hopefully).
You might have to work with constref
or static
keywords as in tests/Method_OfType.lap
.
Actually last time, you had me work with the internal routine that handled "dot", I just don't remember it's name to go back and find how I fixed it.
@nielsAD could we support code like:
{$DEFINE BURGER}
{$IFDEF HOTDOG OR BURGER}
!Error
{$ENDIF}
I am porting a lot of C code over, and I run into code like:
and I don't want to write the {$IFDEF} code twice, nor write:
{$IFDEF WITH_ZLIB}
{$IFDEF WITH_BZLIB2}
{$DEFINE WITH_ZLIB_BZLIB2}
etc. The goal is to keep the code as close to original as possible. But, I am not sure what it would take to add an evaluation for the IFnDEF logic parser.
I'm not sure what we discussed last time regarding fields. You might be able to find it in a mail?
$IF
conditionals shouldn't be that difficult to add, as you can reuse the expression parser and constant evaluation parts. Adding declared
and defined
functions would be a bit more difficult.
@nielsAD what is the correct way to write this in a LAPE script?
type
TDateTimeRec = record
case TFieldType of
ftDate: (
Date: LongInt;
);
ftTime: (
Time: LongInt;
);
ftDateTime: (
DateTime: Double;
);
end;
Is that where I would use a Union? And once coded, how would I access each element?
Thanks again! Ozz
Yes, that should be turned into a union.
type
TDateTimeRec = union
Date: LongInt;
Time: LongInt;
DateTime: Double;
end;
var
dt: TDateTimeRec;
begin
dt.Date := 1;
WriteLn(dt);
end;
Darn, error:
type TDateTimeRec = union Date: LongInt; Time: LongInt; DateTime: Double; end;
var dt: TDateTimeRec; begin dt.Date := 40000; dt.Time := 400; WriteLn(dt); end;
produces: {DATE = 400, TIME = 400, DATETIME = 1.97626258336499E-321}
Looks like union is expecting a single element period… does not understand the grouping of the bytes. Flipping them around JIC still same result: {DATETIME = 1.97626258336499E-321, DATE = 400, TIME = 400}
:-(
On Feb 22, 2017, at 10:07 AM, Niels AD notifications@github.com wrote:
Yes, that should be turned into a union.
type TDateTimeRec = union Date: LongInt; Time: LongInt; DateTime: Double; end;
var dt: TDateTimeRec; begin dt.Date := 1; WriteLn(dt); end; — You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/nielsAD/lape/issues/86#issuecomment-281695449, or mute the thread https://github.com/notifications/unsubscribe-auth/AMlpMstYT4ps4ZcLEVgFBbJD5wf0hrYeks5rfE8igaJpZM4JP-9k.
I get the same result when running this with FreePascal... I'm not sure what you're expecting here?
union = 8 bytes in memory long = bytes 1 2 3 4 long = bytes 5 6 7 8 double = bytes 1..8
?
On Feb 22, 2017, at 11:50 AM, Niels AD notifications@github.com wrote:
I get the same result when running this with FreePascal... I'm not sure what you're expecting here?
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/nielsAD/lape/issues/86#issuecomment-281728557, or mute the thread https://github.com/notifications/unsubscribe-auth/AMlpMohCkzd_Qmml93d95A9DQcV0evZEks5rfGdIgaJpZM4JP-9k.
Use a nested record:
type
TDateTimeRec = union
dt: record
Date: LongInt;
Time: LongInt;
end;
DateTime: Double;
end;
var
rec: TDateTimeRec;
begin
rec.dt := [123, 456];
WriteLn(rec);
end;
Thank you !! That is exactly what I was trying to port over… the pascal code was a record with a case inside it.. I will add this to my notes.
On Feb 22, 2017, at 12:03 PM, Niels AD notifications@github.com wrote:
Use a nested record:
type TDateTimeRec = union dt: record Date: LongInt; Time: LongInt; end; DateTime: Double; end;
var rec: TDateTimeRec; begin rec.dt := [123, 456]; WriteLn(rec); end; — You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/nielsAD/lape/issues/86#issuecomment-281732659, or mute the thread https://github.com/notifications/unsubscribe-auth/AMlpMnx63TokdxUSmmtbkT3AZvip_fyYks5rfGpQgaJpZM4JP-9k.
@nielsAD
I am reviewing Turbo Pascal 7 manual, and came across this - where would be the "correct" place for me to implement this support:
(. .) "A left bracket ([) is equivalent to the character pair of left parenthesis and a period-(., and a right bracket (]) is equivalent to the character pair of a period and a right parenthesis-.)."
You can add this in lpparser.pas
. Just have the parser return it as if it was a regular bracket.
@nielsAD
Hope all is well... is there a way to mimic OnShutdown, or ExitProc. http://putka.upm.si/langref/turboPascal/0681.html
When debugging a script that is running as an Apache Module, I would like to inject some code which documents which function, line, etc. was last running when the error occurred. And if possible, if FileHandle is Open, Close it - as sometimes the error is when I am saving to my log the web variables... without the close, it does not always write the last bit of text.
Ozz
A try
..finally
around your main function should work.
I tried, does not - it has to be something out in lpCompiler/lpInterpreter layer. As I need a way to PUSH into the AST code, Terminate - and it jump to the terminate code. When Apache says kill thread, I can trap the signal, however, the .run() is terminated. So, I was hoping for another way of letting the AST code "hey call this" that I could manually push. I have modified my run() that exception handling is shared with the script and the host - so I can always document the exception if from the script layer. However, sometimes the client disappears (hackers for example) before the script runs, and Apache signals me to abort right now.
If we can figure away to allow the host to do this, it may be useful when implementing a GUI/event driven wrapper... like handling windows events. I
@nielsAD the following code gives me Runtime error: "Invalid jump". Besides not know why, I would like to expand the error to explain what caused the invalid jump.
`uses Math;
const MaxProbability=1000;
type LootType=(Bloodstone, Copper, Emeraldite, Gold, Heronite, Platinum, Shadownite, Silver, Soranite, Umbrarite, Cobalt, Iron, Default); Looter = Class Probabilites:Array[0..12] of Longint; Choose:private function:LootType of object; AsString:private function(l:LootType):String of object; End;
function Looter.Choose:LootType; var Loop,randomValue:Word;
Begin randomValue:=Random(MaxProbability-1); Loop:=0; While Probabilites[Loop mod 12]<randomValue do begin Inc(Loop); End; Result:=LootType(Loop mod 12); End;
function Looter.AsString(l:LootType):String; Begin Case l of LootType(Bloodstone):Result:='Bloodstone'; LootType(Copper):Result:='Copper'; LootType(Emeraldite):Result:='Emeraldite'; LootType(Gold):Result:='Gold'; LootType(Heronite):Result:='Heronite'; LootType(Platinum):Result:='Platinum'; LootType(Shadownite):Result:='Shadownite'; LootType(Silver):Result:='Silver'; LootType(Soranite):Result:='Soranite'; LootType(Umbrarite):Result:='Umbrarite'; LootType(Cobalt):Result:='Cobalt'; LootType(Iron):Result:='Iron'; Else Result:='Iron'; End; End;
procedure Looter.Free; Begin End;
// Must be listed after all actual definitions // procedure Looter.Init; Begin Randomize; with Self do begin Probabilites[0]:=10; Probabilites[1]:=77; Probabilites[2]:=105; Probabilites[3]:=125; Probabilites[4]:=142; Probabilites[5]:=159; Probabilites[6]:=172; Probabilites[7]:=200; Probabilites[8]:=201; Probabilites[9]:=202; Probabilites[10]:=216; Probabilites[11]:=282; Probabilites[12]:=MaxProbability; TMethod(@Choose) := [@Looter.Choose, @Self]; TMethod(@Free) := [@Looter.Free, @Self]; End; End;
var loot:looter; n:longint;
begin loot.init; for n:=0 to 99 do Writeln(Loot.AsString(Loot.choose)); loot.free; end.`
@nielsAD
Finally found the Enum and Set issue - problem is lpvartypes_ord.pas ToString for Enum is using System.SizeInt, System.String, etc ... in my version - System is not defined yet... as I had started implementing NameSpace support (and never finished). Removed "System." in the few places you reference it - and viola, I can writeln Sets and Enumerations without issue.
This fix also allows that last game post to work when changing to Writeln(Loot.Choose);
Regards, Ozz
@nielsAD
I occasionally have this typo, which LAPE does not complain about....
Begin A:=30; B=3; Writeln(A*B); End;
The third line is not doing assignment, code runs, result is wrong. I did it again today, and wasted an hour to find that the issue was the script not the new plugin I was working on. Is it possible see if I am doing a comparison without being in if, while, etc.?
Ozz
@nielsAD - I am tracing through the code to get a better understanding (My Delphi won't trace the code, I had to setup Lazarus/GDB on Linux and it works - so first time in 4+ years I can trace whats going on - and hopefully I will find some of the bugs I have been reporting)... in the meantime, could you explain the usage(s) of these tokens?:
UnImplemented Experimental Deprecated ConstRef External Forward Overload Override Static
@3FLLC The tests work fine, are you sure you're running these tests in lape?
etc..
lpeval_arr.inc @ 3290 fix... (sorry my code structure is not backward compatible to you, so I am manually sharing patches): Arr[op_IN][ltBoolean][ltLargeSet] := Arr[op_IN][ltUInt8][ltLargeSet]; //1180309 @ 3302: Arr[op_Plus][ltLargeSet][ltBoolean] := Arr[op_Plus][ltLargeSet][ltUInt8]; //1180309
lpeval_res.inc @ 3259: Arr[op_Plus][ltSmallSet][ltAnsiChar] := Arr[op_Plus][ltSmallSet][ltUInt8]; // 1180502 [ltSmallSet]; Arr[op_Plus][ltSmallSet][ltWideChar] := Arr[op_Plus][ltSmallSet][ltUInt16]; // 1180502 [ltSmallSet];
@ 3286: Arr[op_IN][ltBoolean][ltLargeSet] := Arr[op_IN][ltUInt8][ltLargeSet]; // 1180309 @ 3295: Arr[op_Plus][ltLargeSet][ltBoolean] := Arr[op_Plus][ltLargeSet][ltUInt8]; // 1180309 Arr[op_Plus][ltLargeSet][ltAnsiChar] := Arr[op_Plus][ltLargeSet][ltUInt8]; // 1180502 [ltLargeSet]; Arr[op_Plus][ltLargeSet][ltWideChar] := Arr[op_Plus][ltLargeSet][ltUInt16]; // 1180502 [ltLargeSet];
@nielsAD can you reproduce this?
program smalltest;
var small: 10..50;
begin
small := 100;
writeln(small) { ??? }
end.
100 is out of range.
Range checks for subranges are not implemented.
@nielsAD
Where would be the best place to implement a quick SaveToFile of the script being compiled (after it has verified all syntax is correct and all methods exist) and after $include have pulled in all include source?
I basically want to save an all in one file - that I can then compress/encrypt - and reference it as a deployable snapshot of the source (like a form of compile, without compilation).
Thanks. Ozz
@3FLLC
override TLapeCompiler.pushTokenizer
, if not InPeek
append the doc to your file.
@nielsAD
A while back you mentioned that I should try posting Bounty(s) for things I would like implemented. Was that here on github, or via another site?
Bounties on my whiteboard:
@nielsAD Okay, I found my memory leak - was in the new namespaces code I added. As I am migrating code, I have a couple questions -
what do these do? autoproperties constaddress coperators
something I touched has broken accessing AnsiString[index], this was working until I started synchronizing lpcompiler lso options - which makes no sense to me: ERROR: Cannot invoke identifier at line 81, column 11 in file "tests/Arithmetics_String.lap