Feature: explicit string representation for enum fields

This commit is contained in:
Araq 2011-01-11 01:09:48 +01:00
commit 1a8c6fb49f
9 changed files with 94 additions and 8 deletions

View file

@ -634,6 +634,24 @@ enums as an index type for arrays. The procedures ``inc``, ``dec``, ``succ``
and ``pred`` are not available for them either. and ``pred`` are not available for them either.
The compiler supports the built-in stringify operator ``$`` for enumerations.
The stringify's result can be controlled by specifying the string values to
use explicitely:
.. code-block:: nimrod
type
TMyEnum = enum
valueA = (0, "my value A"),
valueB = "value B",
valueC = 2,
valueD = (3, "abc")
As can be seen from the example, it is possible to both specify a field's
ordinal value and its string value by using a tuple construction. It is also
possible to only specify one of them.
Subrange types Subrange types
~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~
A `subrange`:idx: type is a range of values from an ordinal type (the base A `subrange`:idx: type is a range of values from an ordinal type (the base

View file

@ -1,14 +1,14 @@
# #
# #
# The Nimrod Compiler # The Nimrod Compiler
# (c) Copyright 2009 Andreas Rumpf # (c) Copyright 2011 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.
# #
#var #var
# newDummyVar: int; // just to check the symbol file mechanism # newDummyVar: int # just to check the symbol file mechanism
# ------------------------- Name Mangling -------------------------------- # ------------------------- Name Mangling --------------------------------
@ -688,7 +688,11 @@ proc genEnumInfo(m: BModule, typ: PType, name: PRope) =
assert(typ.n.sons[i].kind == nkSym) assert(typ.n.sons[i].kind == nkSym)
field = typ.n.sons[i].sym field = typ.n.sons[i].sym
elemNode = getNimNode(m) elemNode = getNimNode(m)
app(enumNames, makeCString(field.name.s)) if field.ast == nil:
# no explicit string literal for the enum field, so use field.name:
app(enumNames, makeCString(field.name.s))
else:
app(enumNames, makeCString(field.ast.strVal))
if i < length - 1: app(enumNames, ", " & tnl) if i < length - 1: app(enumNames, ", " & tnl)
if field.position != i: if field.position != i:
appf(specialCases, "$1.offset = $2;$n", [elemNode, toRope(field.position)]) appf(specialCases, "$1.offset = $2;$n", [elemNode, toRope(field.position)])

View file

@ -58,7 +58,11 @@ proc ordinalValToString(a: PNode): string =
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
if n.sons[i].kind != nkSym: InternalError(a.info, "ordinalValToString") if n.sons[i].kind != nkSym: InternalError(a.info, "ordinalValToString")
var field = n.sons[i].sym var field = n.sons[i].sym
if field.position == x: return field.name.s if field.position == x:
if field.ast == nil:
return field.name.s
else:
return field.ast.strVal
InternalError(a.info, "no symbol for ordinal value: " & $x) InternalError(a.info, "no symbol for ordinal value: " & $x)
else: else:
result = $x result = $x

View file

@ -1,7 +1,7 @@
# #
# #
# The Nimrod Compiler # The Nimrod Compiler
# (c) Copyright 2010 Andreas Rumpf # (c) Copyright 2011 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.
@ -25,7 +25,6 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
counter, x: BiggestInt counter, x: BiggestInt
e: PSym e: PSym
base: PType base: PType
v: PNode
counter = 0 counter = 0
base = nil base = nil
result = newOrPrevType(tyEnum, prev, c) result = newOrPrevType(tyEnum, prev, c)
@ -41,12 +40,25 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
case n.sons[i].kind case n.sons[i].kind
of nkEnumFieldDef: of nkEnumFieldDef:
e = newSymS(skEnumField, n.sons[i].sons[0], c) e = newSymS(skEnumField, n.sons[i].sons[0], c)
v = semConstExpr(c, n.sons[i].sons[1]) var v = semConstExpr(c, n.sons[i].sons[1])
x = getOrdValue(v) var strVal: PNode = nil
case skipTypes(v.typ, abstractInst).kind
of tyTuple:
if sonsLen(v) != 2: liMessage(v.info, errWrongNumberOfVariables)
strVal = v.sons[1] # second tuple part is the string value
if skipTypes(strVal.typ, abstractInst).kind notin {tyString, tyCstring}:
liMessage(strVal.info, errStringLiteralExpected)
x = getOrdValue(v.sons[0]) # first tuple part is the ordinal
of tyString, tyCstring:
strVal = v
x = counter
else:
x = getOrdValue(v)
if i != 1: if i != 1:
if (x != counter): incl(result.flags, tfEnumHasWholes) if (x != counter): incl(result.flags, tfEnumHasWholes)
if x < counter: if x < counter:
liMessage(n.sons[i].info, errInvalidOrderInEnumX, e.name.s) liMessage(n.sons[i].info, errInvalidOrderInEnumX, e.name.s)
e.ast = strVal # might be nil
counter = x counter = x
of nkSym: of nkSym:
e = n.sons[i].sym e = n.sons[i].sym

View file

@ -20,6 +20,7 @@ tcontinuexc.nim;ECcaught
tcopy.nim;TEMP=C:\Programs\xyz\bin tcopy.nim;TEMP=C:\Programs\xyz\bin
tcurrncy.nim;25 tcurrncy.nim;25
temit.nim;509 temit.nim;509
tenumhole;my value A1my value Bconc2valueCabc4abc
texcsub.nim;caught! texcsub.nim;caught!
texplicitgeneric1.nim;Key: 12 value: 12Key: 13 value: 13 Key: A value: 12 Key: B value: 13 texplicitgeneric1.nim;Key: 12 value: 12Key: 13 value: 13 Key: A value: 12 Key: B value: 13
tfinally.nim;came here 3 tfinally.nim;came here 3
@ -44,6 +45,7 @@ tmultim1.nim;7
tmultim2.nim;collide: unit, thing collide: unit, thing collide: thing, unit tmultim2.nim;collide: unit, thing collide: unit, thing collide: thing, unit
tmultim3.nim;Hi derived! tmultim3.nim;Hi derived!
tmultim4.nim;hello tmultim4.nim;hello
tnamedenumfields;my value A0my value Bconc1valueCabc3abc
tnestif.nim;i == 2 tnestif.nim;i == 2
tnestprc.nim;10 tnestprc.nim;10
toop1.nim;34[]o 5 toop1.nim;34[]o 5

1 tack.nim 125
20 tcopy.nim TEMP=C:\Programs\xyz\bin
21 tcurrncy.nim 25
22 temit.nim 509
23 tenumhole my value A1my value Bconc2valueCabc4abc
24 texcsub.nim caught!
25 texplicitgeneric1.nim Key: 12 value: 12Key: 13 value: 13 Key: A value: 12 Key: B value: 13
26 tfinally.nim came here 3
45 tmultim2.nim collide: unit, thing collide: unit, thing collide: thing, unit
46 tmultim3.nim Hi derived!
47 tmultim4.nim hello
48 tnamedenumfields my value A0my value Bconc1valueCabc3abc
49 tnestif.nim i == 2
50 tnestprc.nim 10
51 toop1.nim 34[]o 5

View file

@ -0,0 +1,16 @@
const
strValB = "my value B"
type
TMyEnum = enum
valueA = (1, "my value A"),
valueB = strValB & "conc",
valueC,
valueD = (4, "abc")
# trick the optimizer with a variable:
var x = valueD
echo valueA, ord(valueA), valueB, ord(valueB), valueC, valueD, ord(valueD), x

View file

@ -0,0 +1,17 @@
const
strValB = "my value B"
type
TMyEnum = enum
valueA = (0, "my value A"),
valueB = strValB & "conc",
valueC,
valueD = (3, "abc"),
valueE = 4
# trick the optimizer with a variable:
var x = valueD
echo valueA, ord(valueA), valueB, ord(valueB), valueC, valueD, ord(valueD), x

View file

@ -1,5 +1,7 @@
- we need a way to disable tests - we need a way to disable tests
- deprecate ^ and make it available as operator - deprecate ^ and make it available as operator
- test branch coverage
- checked exceptions
High priority (version 0.9.0) High priority (version 0.9.0)

View file

@ -23,6 +23,13 @@ Bugfixes
anymore. anymore.
Changes affecting backwards compatibility
-----------------------------------------
- Operators starting with ``^`` are now right-associative and have the highest
priority.
Additions Additions
--------- ---------
@ -37,6 +44,10 @@ Additions
- Added ``emit`` pragma for direct code generator control. - Added ``emit`` pragma for direct code generator control.
- Additional operations were added to the ``complex`` module. - Additional operations were added to the ``complex`` module.
- Added ``strutils.formatFloat``, ``strutils.formatBiggestFloat``. - Added ``strutils.formatFloat``, ``strutils.formatBiggestFloat``.
- A field in an ``enum`` may be given an explicit string representation.
This yields more maintainable code than using a constant
``array[TMyEnum, string]`` mapping.
2010-10-20 Version 0.8.10 released 2010-10-20 Version 0.8.10 released