Skip to content

Commit 7855f42

Browse files
committed
compiler: support for once methods on const classes
- Go ahead and make once a first class fcode flag (it was sort of odd case as compiler only flag previously). - Use the once flag on the synthetic storage field for caching - Check once + type.const in JVM emit and set volatile flag
1 parent 10ea2e4 commit 7855f42

File tree

17 files changed

+69
-34
lines changed

17 files changed

+69
-34
lines changed

src/compiler/fan/ast/AstWriter.fan

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ class AstWriter
9292
if (flags.and(FConst.Static) != 0) w("static ")
9393
if (flags.and(FConst.Storage) != 0) w("storage ")
9494
if (flags.and(FConst.Virtual) != 0) w("virtual ")
95+
if (flags.and(FConst.Once) != 0) w("once ")
9596

9697
if (flags.and(FConst.Synthetic) != 0) w("synthetic ")
9798
if (flags.and(FConst.Getter) != 0) w("getter ")

src/compiler/fan/ast/MethodDef.fan

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,6 @@ class MethodDef : SlotDef, CMethod
7373
**
7474
Bool isFieldSetter() { accessorFor != null && paramDefs.size == 1 }
7575

76-
**
77-
** Return if this is a once method
78-
**
79-
Bool isOnce() { flags.and(Parser.Once) != 0 }
80-
8176
**
8277
** Return if this is a constructor with an it-block as last parameter
8378
**

src/compiler/fan/fcode/FConst.fan

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ mixin FConst
4141
const static Int Storage := 0x00010000
4242
const static Int Synthetic := 0x00020000
4343
const static Int Virtual := 0x00040000
44-
const static Int FlagsMask := 0x0007ffff
44+
const static Int Once := 0x00080000
45+
const static Int FlagsMask := 0x000fffff
4546

4647
//////////////////////////////////////////////////////////////////////////
4748
// MethodVarFlags

src/compiler/fan/fcode/FPrinter.fan

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ class FPrinter : FConst
249249
if (flags.and(FConst.Storage) != 0) s.add("storage ")
250250
if (flags.and(FConst.Synthetic) != 0) s.add("synthetic ")
251251
if (flags.and(FConst.Virtual) != 0) s.add("virtual ")
252+
if (flags.and(FConst.Once) != 0) s.add("once ")
252253
return s.toStr[0..-2]
253254
}
254255

src/compiler/fan/namespace/CSlot.fan

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ mixin CSlot
3939
Bool isStorage() { flags.and(FConst.Storage) != 0 }
4040
Bool isSynthetic() { flags.and(FConst.Synthetic) != 0 }
4141
Bool isVirtual() { flags.and(FConst.Virtual) != 0 }
42+
Bool isOnce() { flags.and(FConst.Once) != 0 }
4243

4344
Bool isInstanceCtor() { isCtor && !isStatic }
4445
Bool isStaticCtor() { isCtor && isStatic }

src/compiler/fan/parser/Parser.fan

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ public class Parser : CompilerSupport
283283
case Token.internalKeyword: flags = flags.or(FConst.Internal); protection = true
284284
case Token.nativeKeyword: flags = flags.or(FConst.Native)
285285
case Token.newKeyword: flags = flags.or(FConst.Ctor)
286-
case Token.onceKeyword: flags = flags.or(Once) // Parser only flag
286+
case Token.onceKeyword: flags = flags.or(FConst.Once)
287287
case Token.overrideKeyword: flags = flags.or(FConst.Override)
288288
case Token.privateKeyword: flags = flags.or(FConst.Private); protection = true
289289
case Token.protectedKeyword: flags = flags.or(FConst.Protected); protection = true
@@ -466,7 +466,7 @@ public class Parser : CompilerSupport
466466
field := FieldDef(loc, parent)
467467
field.doc = doc
468468
field.facets = facets
469-
field.flags = flags.and(ParserFlagsMask.not)
469+
field.flags = flags
470470
field.name = name
471471
if (type != null) field.fieldType = type
472472

@@ -2416,11 +2416,6 @@ public class Parser : CompilerSupport
24162416
// Parser Flags
24172417
//////////////////////////////////////////////////////////////////////////
24182418

2419-
// These are flags used only by the parser we merge with FConst
2420-
// flags by starting from most significant bit and working down
2421-
const static Int Once := 0x8000_0000
2422-
const static Int ParserFlagsMask := 0
2423-
24242419
// Bitwise and this mask to clear all protection scope flags
24252420
const static Int ProtectionMask := (FConst.Public).or(FConst.Protected).or(FConst.Private).or(FConst.Internal).not
24262421

src/compiler/fan/steps/CheckErrors.fan

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ class CheckErrors : CompilerStep
119119

120120
// these modifiers are never allowed on a type
121121
if (flags.and(FConst.Ctor) != 0) err("Cannot use 'new' modifier on type", loc)
122-
if (flags.and(Parser.Once) != 0) err("Cannot use 'once' modifier on type", loc)
122+
if (flags.and(FConst.Once) != 0) err("Cannot use 'once' modifier on type", loc)
123123
if (flags.and(FConst.Override) != 0) err("Cannot use 'override' modifier on type", loc)
124124
if (flags.and(FConst.Private) != 0) err("Cannot use 'private' modifier on type", loc)
125125
if (flags.and(FConst.Protected) != 0) err("Cannot use 'protected' modifier on type", loc)
@@ -177,16 +177,9 @@ class CheckErrors : CompilerStep
177177
// in another check
178178
t.fieldDefs.each |FieldDef f|
179179
{
180-
if (!f.isConst && !f.isStatic && f.isStorage && !isSys)
180+
if (!f.isConst && !f.isStatic && f.isStorage && !isSys && !f.isOnce)
181181
err("Const type '$t.name' cannot contain non-const field '$f.name'", f.loc)
182182
}
183-
184-
// check that no once methods
185-
t.methodDefs.each |MethodDef m|
186-
{
187-
if (m.isOnce)
188-
err("Const type '$t.name' cannot contain once method '$m.name'", m.loc)
189-
}
190183
}
191184

192185
private Void checkBase(TypeDef t, CType base)
@@ -256,7 +249,7 @@ class CheckErrors : CompilerStep
256249
// these modifiers are never allowed on a field
257250
if (flags.and(FConst.Ctor) != 0) err("Cannot use 'new' modifier on field", loc)
258251
if (flags.and(FConst.Final) != 0) err("Cannot use 'final' modifier on field", loc)
259-
if (flags.and(Parser.Once) != 0) err("Cannot use 'once' modifier on field", loc)
252+
if (flags.and(FConst.Once) != 0 && flags.and(FConst.Synthetic) == 0) err("Cannot use 'once' modifier on field", loc)
260253

261254
// check invalid protection combinations
262255
checkProtectionFlags(flags, loc)
@@ -380,7 +373,7 @@ class CheckErrors : CompilerStep
380373
if (flags.and(FConst.Abstract) != 0) err("Invalid combination of 'new' and 'abstract' modifiers", loc)
381374
else if (flags.and(FConst.Override) != 0) err("Invalid combination of 'new' and 'override' modifiers", loc)
382375
else if (flags.and(FConst.Virtual) != 0) err("Invalid combination of 'new' and 'virtual' modifiers", loc)
383-
if (flags.and(Parser.Once) != 0) err("Invalid combination of 'new' and 'once' modifiers", loc)
376+
if (flags.and(FConst.Once) != 0) err("Invalid combination of 'new' and 'once' modifiers", loc)
384377
if (flags.and(FConst.Native) != 0) err("Invalid combination of 'new' and 'native' modifiers", loc)
385378
}
386379

@@ -390,18 +383,18 @@ class CheckErrors : CompilerStep
390383
if (flags.and(FConst.Abstract) != 0) err("Invalid combination of 'static' and 'abstract' modifiers", loc)
391384
else if (flags.and(FConst.Override) != 0) err("Invalid combination of 'static' and 'override' modifiers", loc)
392385
else if (flags.and(FConst.Virtual) != 0) err("Invalid combination of 'static' and 'virtual' modifiers", loc)
393-
if (flags.and(Parser.Once) != 0) err("Invalid combination of 'static' and 'once' modifiers", loc)
386+
if (flags.and(FConst.Once) != 0) err("Invalid combination of 'static' and 'once' modifiers", loc)
394387
}
395388

396389
// check invalid abstract flags
397390
if (flags.and(FConst.Abstract) != 0)
398391
{
399392
if (flags.and(FConst.Native) != 0) err("Invalid combination of 'abstract' and 'native' modifiers", loc)
400-
if (flags.and(Parser.Once) != 0) err("Invalid combination of 'abstract' and 'once' modifiers", loc)
393+
if (flags.and(FConst.Once) != 0) err("Invalid combination of 'abstract' and 'once' modifiers", loc)
401394
}
402395

403396
// mixins cannot have once methods
404-
if (flags.and(Parser.Once) != 0)
397+
if (flags.and(FConst.Once) != 0)
405398
{
406399
if (curType.isMixin)
407400
err("Mixins cannot have once methods", m.loc)

src/compiler/fan/steps/Normalize.fan

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -173,8 +173,7 @@ class Normalize : CompilerStep
173173
loc := m.loc
174174

175175
// we'll report these errors in CheckErrors
176-
if (curType.isConst || curType.isMixin ||
177-
m.isStatic || m.isCtor || m.isFieldAccessor)
176+
if (curType.isMixin || m.isStatic || m.isCtor || m.isFieldAccessor)
178177
return
179178

180179
// error checking
@@ -184,7 +183,7 @@ class Normalize : CompilerStep
184183

185184
// generate storage field
186185
f := FieldDef(loc, curType)
187-
f.flags = FConst.Private + FConst.Storage + FConst.Synthetic
186+
f.flags = FConst.Private + FConst.Storage + FConst.Synthetic + FConst.Once
188187
f.name = m.name + "\$Store"
189188
f.fieldType = ns.objType.toNullable
190189
f.init = Expr.makeForLiteral(loc, ns, "_once_")

src/compiler/fan/util/ApiDocWriter.fan

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ class ApiDocWriter
204204
if (flags.and(FConst.Synthetic) != 0) s.join("synthetic")
205205
if (flags.and(FConst.Virtual) != 0) s.join("virtual")
206206
if (flags.and(FConst.Ctor) != 0) s.join("new")
207+
if (flags.and(FConst.Once) != 0) s.join("once")
207208
return s.toStr
208209
}
209210

src/compilerDoc/fan/model/DocFlags.fan

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ final const class DocFlags
3131
const static Int Storage := 0x00010000
3232
const static Int Synthetic := 0x00020000
3333
const static Int Virtual := 0x00040000
34+
const static Int Once := 0x00080000
3435

3536
static Bool isAbstract (Int flags) { flags.and(DocFlags.Abstract) != 0 }
3637
static Bool isConst (Int flags) { flags.and(DocFlags.Const) != 0 }
@@ -51,6 +52,7 @@ final const class DocFlags
5152
static Bool isStorage (Int flags) { flags.and(DocFlags.Storage) != 0 }
5253
static Bool isSynthetic(Int flags) { flags.and(DocFlags.Synthetic) != 0 }
5354
static Bool isVirtual (Int flags) { flags.and(DocFlags.Virtual) != 0 }
55+
static Bool isOnce (Int flags) { flags.and(DocFlags.Once) != 0 }
5456

5557
static Int fromName(Str name)
5658
{

0 commit comments

Comments
 (0)