pastojs: external class const

git-svn-id: trunk@38077 -
This commit is contained in:
Mattias Gaertner 2018-01-29 17:39:06 +00:00
parent f812c657db
commit 6ef4c4af92
4 changed files with 117 additions and 33 deletions

View File

@ -2275,12 +2275,14 @@ begin
RaiseVarModifierNotSupported(ClassFieldModifiersAllowed); RaiseVarModifierNotSupported(ClassFieldModifiersAllowed);
if TPasClassType(El.Parent).IsExternal then if TPasClassType(El.Parent).IsExternal then
begin begin
// external class -> make variable external // external class
if El.Expr<>nil then if El.Visibility=visPublished then
RaiseMsg(20180127111830,nIllegalQualifier,sIllegalQualifier, // Note: an external class has no typeinfo
['='],El.Expr); RaiseMsg(20170413221516,nSymbolCannotBePublished,sSymbolCannotBePublished,
[],El);
if not (vmExternal in El.VarModifiers) then if not (vmExternal in El.VarModifiers) then
begin begin
// make variable external
if (El.ClassType=TPasVariable) or (El.ClassType=TPasConst) then if (El.ClassType=TPasVariable) or (El.ClassType=TPasConst) then
begin begin
if El.ExportName<>nil then if El.ExportName<>nil then
@ -2290,10 +2292,9 @@ begin
end; end;
Include(El.VarModifiers,vmExternal); Include(El.VarModifiers,vmExternal);
end; end;
if El.Visibility=visPublished then if (El.ClassType=TPasConst) and (TPasConst(El).Expr<>nil) then
// Note: an external class has no typeinfo // external const with expression is not writable
RaiseMsg(20170413221516,nSymbolCannotBePublished,sSymbolCannotBePublished, TPasConst(El).IsConst:=true;
[],El);
end; end;
end end
else if ParentC=TPasRecordType then else if ParentC=TPasRecordType then
@ -4970,6 +4971,27 @@ begin
Result:=CreateArgumentAccess(TPasArgument(Decl),AContext,El); Result:=CreateArgumentAccess(TPasArgument(Decl),AContext,El);
exit; exit;
end end
else if Decl.ClassType=TPasConst then
begin
if TPasConst(Decl).IsConst and (TPasConst(Decl).Expr<>nil) then
begin
Value:=AContext.Resolver.Eval(TPasConst(Decl).Expr,[refConst]);
if (Value<>nil)
and (Value.Kind in [revkNil,revkBool,revkInt,revkUInt,revkFloat,revkEnum]) then
try
Result:=ConvertConstValue(Value,AContext,El);
exit;
finally
ReleaseEvalValue(Value);
end;
if vmExternal in TPasConst(Decl).VarModifiers then
begin
// external constant are always added by value, not by reference
Result:=ConvertElement(TPasConst(Decl).Expr,AContext);
exit;
end;
end;
end
else if Decl.ClassType=TPasResString then else if Decl.ClassType=TPasResString then
begin begin
// read resourcestring -> rtl.getResStr($mod,"name") // read resourcestring -> rtl.getResStr($mod,"name")
@ -9758,6 +9780,11 @@ end;
function TPasToJSConverter.ConvertConstValue(Value: TResEvalValue; function TPasToJSConverter.ConvertConstValue(Value: TResEvalValue;
AContext: TConvertContext; El: TPasElement): TJSElement; AContext: TConvertContext; El: TPasElement): TJSElement;
var
Ranges: TResEvalSet.TItems;
Range: TResEvalSet.TItem;
Call: TJSCallExpression;
i: Integer;
begin begin
Result:=nil; Result:=nil;
if Value=nil then if Value=nil then
@ -9783,7 +9810,35 @@ begin
{$IFDEF VerbosePas2JS} {$IFDEF VerbosePas2JS}
writeln('TPasToJSConverter.ConvertConstValue Value=',Value.AsDebugString,' IdentEl=',GetObjName(Value.IdentEl)); writeln('TPasToJSConverter.ConvertConstValue Value=',Value.AsDebugString,' IdentEl=',GetObjName(Value.IdentEl));
{$ENDIF} {$ENDIF}
RaiseNotSupported(El,AContext,20171221125842); // rtl.createSet()
Call:=CreateCallExpression(El);
try
Call.Expr:=CreateMemberExpression([FBuiltInNames[pbivnRTL],FBuiltInNames[pbifnSet_Create]]);
Ranges:=TResEvalSet(Value).Ranges;
for i:=0 to length(Ranges)-1 do
begin
Range:=Ranges[i];
{$IFDEF VerbosePas2JS}
writeln('TPasToJSConverter.ConvertConstValue SetLiteral ',i,' ',Range.RangeStart,'..',Range.RangeEnd);
{$ENDIF}
if Range.RangeStart=Range.RangeEnd then
begin
// add one integer
Call.AddArg(CreateLiteralNumber(El,Range.RangeStart));
end
else
begin
// range -> add three parameters: null,left,right
Call.AddArg(CreateLiteralNull(El));
Call.AddArg(CreateLiteralNumber(El,Range.RangeStart));
Call.AddArg(CreateLiteralNumber(El,Range.RangeEnd));
end;
end;
Result:=Call;
finally
if Result=nil then
Call.Free;
end;
end end
else else
{$IFDEF VerbosePas2JS} {$IFDEF VerbosePas2JS}

View File

@ -109,7 +109,7 @@ constructor TPas2jsPasParser.Create(AScanner: TPascalScanner;
AFileResolver: TBaseFileResolver; AEngine: TPasTreeContainer); AFileResolver: TBaseFileResolver; AEngine: TPasTreeContainer);
begin begin
inherited Create(AScanner,AFileResolver,AEngine); inherited Create(AScanner,AFileResolver,AEngine);
Options:=Options+[po_asmwhole,po_resolvestandardtypes]; Options:=Options+[po_AsmWhole,po_ResolveStandardTypes,po_ExtClassConstWithoutExpr];
end; end;
procedure TPas2jsPasParser.SetLastMsg(MsgType: TMessageType; procedure TPas2jsPasParser.SetLastMsg(MsgType: TMessageType;

View File

@ -31,7 +31,7 @@ uses
const const
// default parser+scanner options // default parser+scanner options
po_pas2js = [po_asmwhole,po_resolvestandardtypes]; po_pas2js = [po_asmwhole,po_resolvestandardtypes,po_ExtClassConstWithoutExpr];
co_tcmodules = [coNoTypeInfo]; co_tcmodules = [coNoTypeInfo];
type type
@ -427,7 +427,7 @@ type
// external class // external class
Procedure TestExternalClass_Var; Procedure TestExternalClass_Var;
Procedure TestExternalClass_ConstFail; Procedure TestExternalClass_Const;
Procedure TestExternalClass_Dollar; Procedure TestExternalClass_Dollar;
Procedure TestExternalClass_DuplicateVarFail; Procedure TestExternalClass_DuplicateVarFail;
Procedure TestExternalClass_Method; Procedure TestExternalClass_Method;
@ -3144,10 +3144,10 @@ begin
CheckSource('TestProc_ConstOrder', CheckSource('TestProc_ConstOrder',
LinesToStr([ // statements LinesToStr([ // statements
'this.A = 3;', 'this.A = 3;',
'this.B = $mod.A + 1;', 'this.B = 3 + 1;',
'var C = $mod.A + 1;', 'var C = 3 + 1;',
'var D = $mod.B + 1;', 'var D = 4 + 1;',
'var E = ((D + C) + $mod.B) + $mod.A;', 'var E = ((5 + 4) + 4) + 3;',
'this.DoIt = function () {', 'this.DoIt = function () {',
'};', '};',
'']), '']),
@ -3933,10 +3933,10 @@ begin
'this.Enums = {};', 'this.Enums = {};',
'']), '']),
LinesToStr([ LinesToStr([
'$mod.Enums = rtl.includeSet($mod.Enums, $mod.Orange);', '$mod.Enums = rtl.includeSet($mod.Enums, $mod.TEnum.Red);',
'$mod.Enums = rtl.excludeSet($mod.Enums, $mod.Orange);', '$mod.Enums = rtl.excludeSet($mod.Enums, $mod.TEnum.Red);',
'if ($mod.Orange in $mod.Enums) ;', 'if ($mod.TEnum.Red in $mod.Enums) ;',
'if ($mod.Orange in rtl.createSet($mod.Orange, $mod.TEnum.Red)) ;', 'if ($mod.TEnum.Red in rtl.createSet($mod.TEnum.Red, $mod.TEnum.Red)) ;',
''])); '']));
end; end;
@ -3977,16 +3977,16 @@ begin
'']), '']),
LinesToStr([ LinesToStr([
'$mod.f = rtl.includeSet($mod.f, $mod.TFlags$a.red);', '$mod.f = rtl.includeSet($mod.f, $mod.TFlags$a.red);',
'$mod.f = rtl.includeSet($mod.f, $mod.favorite);', '$mod.f = rtl.includeSet($mod.f, $mod.TFlags$a.red);',
'$mod.i = $mod.TFlags$a.red;',
'$mod.i = $mod.TFlags$a.red;', '$mod.i = $mod.TFlags$a.red;',
'$mod.i = $mod.favorite;',
'$mod.i = $mod.TFlags$a.red;', '$mod.i = $mod.TFlags$a.red;',
'$mod.i = $mod.TFlags$a.red;', '$mod.i = $mod.TFlags$a.red;',
'$mod.i = $mod.TFlags$a.red;', '$mod.i = $mod.TFlags$a.red;',
'$mod.i = $mod.TFlags$a.green;', '$mod.i = $mod.TFlags$a.green;',
'$mod.i = $mod.TFlags$a.green;', '$mod.i = $mod.TFlags$a.green;',
'$mod.i = $mod.TFlags$a.green;', '$mod.i = $mod.TFlags$a.green;',
'$mod.f = rtl.createSet($mod.TFlags$a.green, $mod.favorite);', '$mod.f = rtl.createSet($mod.TFlags$a.green, $mod.TFlags$a.red);',
''])); '']));
end; end;
@ -4301,10 +4301,10 @@ begin
'var cB$1 = 4;', 'var cB$1 = 4;',
'this.DoIt = function () {', 'this.DoIt = function () {',
' function Sub() {', ' function Sub() {',
' cB$1 = cB$1 + csA;', ' cB$1 = cB$1 + 3;',
' cA = (cA + csA) + 5;', ' cA = (cA + 3) + 5;',
' };', ' };',
' cA = (cA + cB) + 6;', ' cA = (cA + 2) + 6;',
'};' '};'
]), ]),
LinesToStr([ LinesToStr([
@ -10480,18 +10480,47 @@ begin
''])); '']));
end; end;
procedure TTestModule.TestExternalClass_ConstFail; procedure TTestModule.TestExternalClass_Const;
begin begin
StartProgram(false); StartProgram(false);
Add([ Add([
'{$modeswitch externalclass}', '{$modeswitch externalclass}',
'type', 'type',
' TExtA = class external name ''ExtObj''', ' TExtA = class external name ''ExtObj''',
' const Id: longint = 3;', ' const Two: longint = 2;',
' const Three = 3;',
' const Id: longint;',
' end;', ' end;',
'begin']); ' TExtB = class external name ''ExtB''',
SetExpectedPasResolverError('illegal qualifier "="',nIllegalQualifier); ' A: TExtA;',
' end;',
'var',
' A: texta;',
' B: textb;',
' i: longint;',
'begin',
' i:=a.two;',
' i:=texta.two;',
' i:=a.three;',
' i:=texta.three;',
' i:=a.id;',
' i:=texta.id;',
'']);
ConvertProgram; ConvertProgram;
CheckSource('TestExternalClass_Dollar',
LinesToStr([ // statements
'this.A = null;',
'this.B = null;',
'this.i = 0;',
'']),
LinesToStr([ // $mod.$main
'$mod.i = 2;',
'$mod.i = 2;',
'$mod.i = 3;',
'$mod.i = 3;',
'$mod.i = $mod.A.Id;',
'$mod.i = ExtObj.Id;',
'']));
end; end;
procedure TTestModule.TestExternalClass_Dollar; procedure TTestModule.TestExternalClass_Dollar;
@ -11111,7 +11140,7 @@ begin
Add(' constructor New;'); Add(' constructor New;');
Add(' end;'); Add(' end;');
Add('function DoIt: longint;'); Add('function DoIt: longint;');
Add('const ExtA = 3;'); Add('const ExtA: longint = 3;');
Add('begin'); Add('begin');
Add(' Result:=ExtA;'); Add(' Result:=ExtA;');
Add('end;'); Add('end;');

View File

@ -264,7 +264,7 @@ begin
'var d = 6;', 'var d = 6;',
'this.DoIt = function () {', 'this.DoIt = function () {',
' var Result = 0;', ' var Result = 0;',
' Result = b + d;', ' Result = 4 + d;',
' return Result;', ' return Result;',
'};', '};',
'']), '']),
@ -819,7 +819,7 @@ begin
' });', ' });',
' this.T = null;', ' this.T = null;',
' $mod.$main = function () {', ' $mod.$main = function () {',
' $mod.T = $mod.TObject.$create("Create",[$mod.gcBlack]);', ' $mod.T = $mod.TObject.$create("Create",[0]);',
' };', ' };',
'});', '});',
'']); '']);