Add support for importing enum types and enum values (as constexprs).
Add support for importing enum types and enum values (as constexprs).
1.1 --- a/src/ObjectVisitor.h Sat Jan 12 16:35:26 2013 -0800
1.2 +++ b/src/ObjectVisitor.h Sun Jan 27 17:34:30 2013 -0800
1.3 @@ -54,6 +54,7 @@
1.4
1.5 size_t iterateEnumType(Object *obj) {
1.6 visitField(obj, EnumType::offsetOfName());
1.7 + visitField(obj, EnumType::offsetOfFields());
1.8 return sizeof(EnumType);
1.9 }
1.10
2.1 --- a/src/RootScopes.h Sat Jan 12 16:35:26 2013 -0800
2.2 +++ b/src/RootScopes.h Sun Jan 27 17:34:30 2013 -0800
2.3 @@ -2,19 +2,19 @@
2.4 *
2.5 * Copyright (C) 2012 David Anderson
2.6 *
2.7 - * This file is part of JITCraft.
2.8 + * This file is part of SourcePawn.
2.9 *
2.10 - * JITCraft is free software: you can redistribute it and/or modify it under
2.11 + * SourcePawn is free software: you can redistribute it and/or modify it under
2.12 * the terms of the GNU General Public License as published by the Free
2.13 * Software Foundation, either version 3 of the License, or (at your option)
2.14 * any later version.
2.15 *
2.16 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
2.17 + * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
2.18 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
2.19 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
2.20 *
2.21 * You should have received a copy of the GNU General Public License along with
2.22 - * JITCraft. If not, see http://www.gnu.org/licenses/.
2.23 + * SourcePawn. If not, see http://www.gnu.org/licenses/.
2.24 */
2.25 #ifndef _include_jc_root_scopes_h_
2.26 #define _include_jc_root_scopes_h_
3.1 --- a/src/TypeManager.cpp Sat Jan 12 16:35:26 2013 -0800
3.2 +++ b/src/TypeManager.cpp Sun Jan 27 17:34:30 2013 -0800
3.3 @@ -52,6 +52,10 @@
3.4 if (!importableType_)
3.5 return false;
3.6
3.7 + typeType_ = Type::NewType(zone_);
3.8 + if (!typeType_)
3.9 + return false;
3.10 +
3.11 if ((primitiveTypes_[PrimitiveType_Int32] = Type::NewPrimitive(zone_, PrimitiveType_Int32)) == NULL)
3.12 return false;
3.13 if ((primitiveTypes_[PrimitiveType_Float] = Type::NewPrimitive(zone_, PrimitiveType_Float)) == NULL)
3.14 @@ -141,6 +145,7 @@
3.15 visitor->visit(uncheckedType_.address());
3.16 visitor->visit(stringType_.address());
3.17 visitor->visit(importableType_.address());
3.18 + visitor->visit(typeType_.address());
3.19 for (unsigned i = 0; i < PrimitiveTypes_Total; i++) {
3.20 visitor->visit(primitiveTypes_[i].address());
3.21 visitor->visit(referenceTypes_[i].address());
4.1 --- a/src/TypeManager.h Sat Jan 12 16:35:26 2013 -0800
4.2 +++ b/src/TypeManager.h Sun Jan 27 17:34:30 2013 -0800
4.3 @@ -82,6 +82,9 @@
4.4 Type *getImportable() {
4.5 return importableType_;
4.6 }
4.7 + Type *getType() {
4.8 + return typeType_;
4.9 + }
4.10 ReferenceType *getReference(Handle<Type> type, bool isConst);
4.11 ArrayType *newArray(Handle<Type> contained, int elements);
4.12 ArrayType *newExternalArray(Handle<Type> contained);
4.13 @@ -100,6 +103,7 @@
4.14 Unbarriered<Type> stringType_;
4.15 Unbarriered<Type> uncheckedType_;
4.16 Unbarriered<Type> importableType_;
4.17 + Unbarriered<Type> typeType_;
4.18 Unbarriered<Type> primitiveTypes_[PrimitiveTypes_Total];
4.19 Unbarriered<ReferenceType> referenceTypes_[PrimitiveTypes_Total];
4.20
5.1 --- a/src/Types.cpp Sat Jan 12 16:35:26 2013 -0800
5.2 +++ b/src/Types.cpp Sun Jan 27 17:34:30 2013 -0800
5.3 @@ -78,6 +78,17 @@
5.4 }
5.5
5.6 Type *
5.7 +Type::NewType(Zone *zone)
5.8 +{
5.9 + Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
5.10 + if (!type)
5.11 + return NULL;
5.12 +
5.13 + type->init(TYPE);
5.14 + return type;
5.15 +}
5.16 +
5.17 +Type *
5.18 Type::NewPrimitive(Zone *zone, PrimitiveType prim)
5.19 {
5.20 Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
5.21 @@ -167,6 +178,7 @@
5.22
5.23 type->init(ENUM);
5.24 type->name_ = name;
5.25 + type->fields_ = NULL;
5.26 return type;
5.27 }
5.28
6.1 --- a/src/Types.h Sat Jan 12 16:35:26 2013 -0800
6.2 +++ b/src/Types.h Sun Jan 27 17:34:30 2013 -0800
6.3 @@ -65,7 +65,11 @@
6.4 TypeQual_None = 0,
6.5
6.6 // Values of this type cannot be modified.
6.7 - TypeQual_Const = (1 << 2)
6.8 + TypeQual_Const = (1 << 0),
6.9 +
6.10 + // Values of this type can be treated as constant expressions. This allows
6.11 + // us to export compile-time constants from modules.
6.12 + TypeQual_ConstExpr = (1 << 1)
6.13 };
6.14
6.15 class Type : public Object
6.16 @@ -115,7 +119,10 @@
6.17
6.18 // Importable types are mainly used during the compilation process
6.19 // to distinguish between normal names and static imports.
6.20 - IMPORTABLE
6.21 + IMPORTABLE,
6.22 +
6.23 + // The type of types.
6.24 + TYPE
6.25 };
6.26
6.27 void init(Kind kind, Type *root = NULL);
6.28 @@ -128,6 +135,7 @@
6.29 public:
6.30 static Type *NewVoid(Zone *zone);
6.31 static Type *NewUnchecked(Zone *zone);
6.32 + static Type *NewType(Zone *zone);
6.33 static Type *NewPrimitive(Zone *zone, PrimitiveType type);
6.34 static Type *NewString(Zone *zone);
6.35 static Type *NewQualified(Zone *zone, TypeQualifiers qual, Handle<Type> type);
6.36 @@ -210,6 +218,9 @@
6.37 bool isEnum() {
6.38 return kind() == ENUM;
6.39 }
6.40 + bool isType() {
6.41 + return kind() == TYPE;
6.42 + }
6.43 bool hasTypeQualifiers() {
6.44 return kind_ == QUALTYPE;
6.45 }
6.46 @@ -252,6 +263,9 @@
6.47 static inline size_t offsetOfName() {
6.48 return OFFSETOF(EnumType, name_);
6.49 }
6.50 + static inline size_t offsetOfFields() {
6.51 + return OFFSETOF(EnumType, fields_);
6.52 + }
6.53 // End GC Descriptor.
6.54
6.55 static EnumType *cast(Object *obj) {
6.56 @@ -261,6 +275,7 @@
6.57
6.58 private:
6.59 Barriered<String> name_;
6.60 + Barriered<FixedArray> fields_;
6.61 };
6.62
6.63 class ReferenceType : public Type
7.1 --- a/src/compiler/AST.h Sat Jan 12 16:35:26 2013 -0800
7.2 +++ b/src/compiler/AST.h Sun Jan 27 17:34:30 2013 -0800
7.3 @@ -873,11 +873,13 @@
7.4 ScopedRoot<String> name;
7.5 Expression *expr;
7.6 SourcePosition pos;
7.7 + ConstantSymbol *sym;
7.8
7.9 Entry(Handle<String> name, Expression *expr, const SourcePosition &pos)
7.10 : name(name),
7.11 expr(expr),
7.12 - pos(pos)
7.13 + pos(pos),
7.14 + sym(NULL)
7.15 {
7.16 }
7.17 };
7.18 @@ -885,17 +887,18 @@
7.19 typedef PoolList<Entry> EntryList;
7.20
7.21 public:
7.22 - EnumStatement(const SourcePosition &pos, Handle<String> name, EntryList *entries)
7.23 + EnumStatement(const SourcePosition &pos, TokenKind visibility, Handle<String> name, EntryList *entries)
7.24 : Statement(pos),
7.25 name_(name),
7.26 sym_(NULL),
7.27 - entries_(entries)
7.28 + entries_(entries),
7.29 + visibility_(visibility)
7.30 {
7.31 }
7.32
7.33 DECLARE_NODE(EnumStatement);
7.34
7.35 - String *name() const {
7.36 + Handle<String> name() const {
7.37 return name_;
7.38 }
7.39 EntryList *entries() const {
7.40 @@ -908,9 +911,13 @@
7.41 TypeSymbol *sym() const {
7.42 return sym_;
7.43 }
7.44 + TokenKind visibility() const {
7.45 + return visibility_;
7.46 + }
7.47
7.48 private:
7.49 EntryList *entries_;
7.50 + TokenKind visibility_;
7.51 };
7.52
7.53 class IncDecExpression : public Expression
8.1 --- a/src/compiler/CompileContext.h Sat Jan 12 16:35:26 2013 -0800
8.2 +++ b/src/compiler/CompileContext.h Sun Jan 27 17:34:30 2013 -0800
8.3 @@ -62,7 +62,7 @@
8.4 importScope_(NULL),
8.5 globalScope_(NULL),
8.6 module_(module),
8.7 - oom_(false),
8.8 + enoughMemory_(true),
8.9 dependencyFailed_(false)
8.10 {
8.11 }
8.12 @@ -83,7 +83,7 @@
8.13 }
8.14 bool failed() const {
8.15 return errors_.length() ||
8.16 - oom_ ||
8.17 + !enoughMemory_ ||
8.18 dependencyFailed_;
8.19 }
8.20 void setImportScope(ImportScope *scope) {
8.21 @@ -108,17 +108,17 @@
8.22 dependencyFailed_ = true;
8.23 }
8.24 void setOutOfMemory() {
8.25 - oom_ = true;
8.26 + enoughMemory_ = false;
8.27 }
8.28 void appendError(const char *report, unsigned line, unsigned col) {
8.29 - oom_ |= errors_.append(CompileError(line, col, report));
8.30 + enoughMemory_ |= errors_.append(CompileError(line, col, report));
8.31 }
8.32 const Vector<CompileError> *errors() {
8.33 return &errors_;
8.34 }
8.35
8.36 private:
8.37 - bool oom_;
8.38 + bool enoughMemory_;
8.39 bool dependencyFailed_;
8.40 Vector<CompileError> errors_;
8.41 };
9.1 --- a/src/compiler/NameBinding.cpp Sat Jan 12 16:35:26 2013 -0800
9.2 +++ b/src/compiler/NameBinding.cpp Sun Jan 27 17:34:30 2013 -0800
9.3 @@ -137,12 +137,14 @@
9.4 return;
9.5 }
9.6
9.7 - bool declareSystemType(ImportScope *scope, const char *name, Handle<Type> type) {
9.8 + bool declareSystemType(ImportScope *scope, const char *name, Handle<Type> effective) {
9.9 Local<String> tag(zone_, zone_->makeSymbol(name));
9.10 if (!tag)
9.11 return false;
9.12
9.13 - TypeSymbol *sym = new (pool_) TypeSymbol(scope, tag, type);
9.14 + Local<Type> type(zone_, zone_->types()->getType());
9.15 +
9.16 + TypeSymbol *sym = new (pool_) TypeSymbol(scope, tag, type, effective);
9.17 return scope->addSymbol(sym);
9.18 }
9.19
9.20 @@ -214,7 +216,8 @@
9.21 return;
9.22
9.23 if (name) {
9.24 - TypeSymbol *sym = new (pool_) TypeSymbol(scope, name, type);
9.25 + Local<Type> symType(zone_, zone_->types()->getType());
9.26 + TypeSymbol *sym = new (pool_) TypeSymbol(scope, name, symType, type);
9.27 if (!registerName(scope, sym))
9.28 return;
9.29
9.30 @@ -224,6 +227,10 @@
9.31 }
9.32 }
9.33
9.34 + // We want each field of the expression to qualify as a constant expression.
9.35 + if ((type = zone_->types()->qualify(type, TypeQual_ConstExpr)) == NULL)
9.36 + return;
9.37 +
9.38 int value = 0;
9.39 for (size_t i = 0; i < node->entries()->length(); i++) {
9.40 EnumStatement::Entry &entry = node->entries()->at(i);
9.41 @@ -237,7 +244,7 @@
9.42 assert(box.type() == PrimitiveType_Int32);
9.43 value = box.toInt();
9.44 }
9.45 -
9.46 +
9.47 ConstantSymbol *sym = new (pool_) ConstantSymbol(scope, entry.name, entry.pos, type, box);
9.48 if (!registerName(scope, sym))
9.49 return;
9.50 @@ -246,6 +253,7 @@
9.51 return;
9.52 }
9.53
9.54 + entry.sym = sym;
9.55 value++;
9.56 }
9.57 }
9.58 @@ -756,7 +764,7 @@
9.59 return NULL;
9.60 }
9.61
9.62 - type = sym->type();
9.63 + type = sym->toType()->effective();
9.64 }
9.65
9.66 return zone_->types()->qualify(type, quals);
9.67 @@ -771,6 +779,18 @@
9.68
9.69 class GlobalBuilder : public NameBinderBase
9.70 {
9.71 + typedef ScopedRoot<Descriptor> ScopedDescriptor;
9.72 + struct PrimitiveFill {
9.73 + ScopedDescriptor *desc;
9.74 + BoxedPrimitive prim;
9.75 +
9.76 + PrimitiveFill(ScopedDescriptor *desc, BoxedPrimitive prim)
9.77 + : desc(desc),
9.78 + prim(prim)
9.79 + {
9.80 + }
9.81 + };
9.82 +
9.83 public:
9.84 GlobalBuilder(Zone *zone, CompileContext &cc, TranslationUnit *unit)
9.85 : NameBinderBase(zone, cc, unit),
9.86 @@ -788,6 +808,17 @@
9.87 stmt->accept(this);
9.88 }
9.89
9.90 + Local<Struct> globals(zone_, createGlobals());
9.91 + if (!globals)
9.92 + return NULL;
9.93 +
9.94 + populate(globals);
9.95 +
9.96 + return globals;
9.97 + }
9.98 +
9.99 + private:
9.100 + Struct *createGlobals() {
9.101 Local<FixedArray> descs(zone_, FixedArray::New(zone_, descriptors_.length(), Heap::Tenure_Old));
9.102 if (!descs)
9.103 return NULL;
9.104 @@ -804,7 +835,47 @@
9.105 return Struct::New(zone_, map, Heap::Tenure_Old);
9.106 }
9.107
9.108 + void populate(Handle<Struct> globals) {
9.109 + // This is a huge hack, but it's probably better than a full extra
9.110 + // pass. The problem is that until we have all the descriptors, we
9.111 + // can't start setting constexprs in the struct, and we need to set
9.112 + // them now so they're available during full semantic analysis. To
9.113 + // work around this, we build up the list of values we need to set
9.114 + // as we build up descriptors, and then populate the global struct
9.115 + // with this set.
9.116 + //
9.117 + // Note, this code is also kind of dead until we support linking. We
9.118 + // handle constexprs explicitly in importFrom(), by sniffing out the
9.119 + // symbol type. That code will go away later.
9.120 + for (size_t i = 0; i < primitiveFills_.length(); i++) {
9.121 + const PrimitiveFill &fill = primitiveFills_[i];
9.122 + assert(fill.prim.type() == PrimitiveType_Int32);
9.123 + globals->set(*fill.desc, fill.prim.toInt());
9.124 + }
9.125 + }
9.126 +
9.127 + public:
9.128 void visitEnumStatement(EnumStatement *stmt) {
9.129 + if (stmt->visibility() != TOK_PUBLIC || !stmt->name())
9.130 + return;
9.131 +
9.132 + Local<Type> type(zone_, zone_->types()->getType());
9.133 + Descriptor *desc = Descriptor::New(zone_, stmt->name(), type, Descriptor::Public);
9.134 + if (!desc)
9.135 + return;
9.136 + if (!descriptors_.append(new (pool_) ScopedRoot<Descriptor>(desc)))
9.137 + return;
9.138 +
9.139 + for (size_t i = 0; i < stmt->entries()->length(); i++) {
9.140 + EnumStatement::Entry &e = stmt->entries()->at(i);
9.141 + ScopedDescriptor *desc = new (pool_) ScopedDescriptor(Descriptor::New(zone_, e.name, e.sym->type(), Descriptor::Public));
9.142 + if (!desc || !descriptors_.append(desc))
9.143 + return;
9.144 +
9.145 + // Save the value so we can export it immediately.
9.146 + if (!primitiveFills_.append(PrimitiveFill(desc, e.sym->value())))
9.147 + return;
9.148 + }
9.149 }
9.150
9.151 void visitNameProxy(NameProxy *proxy) {
9.152 @@ -917,11 +988,33 @@
9.153 return false;
9.154 }
9.155
9.156 - ImplicitSymbol *sym = new (pool_) ImplicitSymbol(unit_->importScope(),
9.157 - import->name(),
9.158 - node->pos(),
9.159 - import->type(),
9.160 - node->importIndex());
9.161 + Symbol *sym;
9.162 + if (import->isType()) {
9.163 + // Fuck it, make a TypeSymbol instead of an ImplicitSymbol. This
9.164 + // makes bindType() much simpler. We may run into problems
9.165 + // implementing linking, but it seems unlikely, as long as we are
9.166 + // exporting Types in module structs.
9.167 + Local<Type> type(zone_, zone_->types()->getType());
9.168 + sym = new (pool_) TypeSymbol(unit_->importScope(),
9.169 + import->name(),
9.170 + type,
9.171 + import->toType()->effective());
9.172 + } else if (import->isConstant()) {
9.173 + // Same deal. No reason to lookup in the module globals if we
9.174 + // already have a symbol.
9.175 + sym = new (pool_) ConstantSymbol(unit_->importScope(),
9.176 + import->name(),
9.177 + node->pos(),
9.178 + import->type(),
9.179 + import->toConstant()->value());
9.180 + } else {
9.181 + sym = new (pool_) ImplicitSymbol(unit_->importScope(),
9.182 + import->name(),
9.183 + node->pos(),
9.184 + import->type(),
9.185 + node->importIndex());
9.186 + }
9.187 +
9.188 if (!unit_->importScope()->addSymbol(sym))
9.189 return false;
9.190
9.191 @@ -963,6 +1056,7 @@
9.192 StructureBufferBuilder builder_;
9.193 Vector<ScopedRoot<Descriptor> *> descriptors_;
9.194 GlobalScope *globalScope_;
9.195 + Vector<PrimitiveFill> primitiveFills_;
9.196 };
9.197
9.198 class NameBinder : public NameBinderBase
10.1 --- a/src/compiler/Parser.cpp Sat Jan 12 16:35:26 2013 -0800
10.2 +++ b/src/compiler/Parser.cpp Sun Jan 27 17:34:30 2013 -0800
10.3 @@ -1106,7 +1106,7 @@
10.4 break;
10.5
10.6 case TOK_ENUM:
10.7 - if ((statement = enum_()) == NULL)
10.8 + if ((statement = enum_(TOK_NONE)) == NULL)
10.9 return NULL;
10.10 break;
10.11
10.12 @@ -1189,7 +1189,7 @@
10.13 }
10.14
10.15 Statement *
10.16 -Parser::enum_()
10.17 +Parser::enum_(TokenKind kind)
10.18 {
10.19 // enum ::= "enum" name? { enum_members? }
10.20 // enum_members ::= enum_member ","? |
10.21 @@ -1229,7 +1229,7 @@
10.22 if (!expect(TOK_RBRACE))
10.23 return NULL;
10.24
10.25 - return new (pool_) EnumStatement(pos, name, entries);
10.26 + return new (pool_) EnumStatement(pos, kind, name, entries);
10.27 }
10.28
10.29 template <class T>
10.30 @@ -1460,6 +1460,11 @@
10.31 return NULL;
10.32 if (!matchSemicolon())
10.33 return NULL;
10.34 + } else if (kind == TOK_PUBLIC && peek(TOK_ENUM)) {
10.35 + if ((statement = enum_(kind)) == NULL)
10.36 + return NULL;
10.37 + if (!matchSemicolon())
10.38 + return NULL;
10.39 } else {
10.40 if ((statement = function(kind)) == NULL)
10.41 return NULL;
10.42 @@ -1485,7 +1490,7 @@
10.43 }
10.44
10.45 case TOK_ENUM:
10.46 - if ((statement = enum_()) == NULL)
10.47 + if ((statement = enum_(TOK_NONE)) == NULL)
10.48 return NULL;
10.49 if (!matchSemicolon())
10.50 return NULL;
11.1 --- a/src/compiler/Parser.h Sat Jan 12 16:35:26 2013 -0800
11.2 +++ b/src/compiler/Parser.h Sun Jan 27 17:34:30 2013 -0800
11.3 @@ -82,7 +82,7 @@
11.4
11.5 Statement *switch_();
11.6 Statement *struct_();
11.7 - Statement *enum_();
11.8 + Statement *enum_(TokenKind kind);
11.9 Statement *if_();
11.10 Statement *block();
11.11 Statement *function(TokenKind tok);
12.1 --- a/src/compiler/SemanticAnalysis.cpp Sat Jan 12 16:35:26 2013 -0800
12.2 +++ b/src/compiler/SemanticAnalysis.cpp Sun Jan 27 17:34:30 2013 -0800
12.3 @@ -1103,7 +1103,7 @@
12.4 if (from->isInt32() && to->isBool())
12.5 return new (pool_) HConvert(hir->node(), to, OP_CVT_I2B, hir);
12.6
12.7 - if (to->isEnum() && *from != to)
12.8 + if (to->isEnum() && from->unqualified() != to->unqualified())
12.9 return typeFailure(hir->node()->pos(), from, to);
12.10
12.11 if (to->isArray()) {
12.12 @@ -1231,10 +1231,10 @@
12.13 return;
12.14 }
12.15
12.16 - if (!IsValidUncheckedType(sym->type())) {
12.17 + if (!IsValidUncheckedType(sym->effective())) {
12.18 char name[255];
12.19 cc_.reportError(node->pos(), Message_InvalidUncheckedCastTo,
12.20 - GetTypeName(hir->type(), name, sizeof(name)));
12.21 + GetTypeName(sym->type(), name, sizeof(name)));
12.22 return;
12.23 }
12.24 if (!IsValidUncheckedType(hir->type())) {
12.25 @@ -1244,7 +1244,7 @@
12.26 return;
12.27 }
12.28
12.29 - hir_ = new (pool_) HUnary(node, hir->type(), TOK_LABEL, hir);
12.30 + hir_ = new (pool_) HUnary(node, sym->effective(), TOK_LABEL, hir);
12.31 break;
12.32 }
12.33 }
13.1 --- a/src/compiler/Symbols.h Sat Jan 12 16:35:26 2013 -0800
13.2 +++ b/src/compiler/Symbols.h Sun Jan 27 17:34:30 2013 -0800
13.3 @@ -160,8 +160,9 @@
13.4 class TypeSymbol : public Symbol
13.5 {
13.6 public:
13.7 - TypeSymbol(Scope *scope, Handle<String> name, Handle<Type> type)
13.8 - : Symbol(scope, name, SourcePosition())
13.9 + TypeSymbol(Scope *scope, Handle<String> name, Handle<Type> type, Handle<Type> effective)
13.10 + : Symbol(scope, name, SourcePosition()),
13.11 + effective_(effective)
13.12 {
13.13 type_ = type;
13.14 }
13.15 @@ -169,6 +170,12 @@
13.16 Kind kind() const {
13.17 return kType;
13.18 }
13.19 + Handle<Type> effective() {
13.20 + return effective_;
13.21 + }
13.22 +
13.23 + private:
13.24 + ScopedRoot<Type> effective_;
13.25 };
13.26
13.27 class FunctionSymbol : public Symbol
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
14.2 +++ b/tests/basic/import_enum_a.out Sun Jan 27 17:34:30 2013 -0800
14.3 @@ -0,0 +1,1 @@
14.4 +2
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
15.2 +++ b/tests/basic/import_enum_a.sp Sun Jan 27 17:34:30 2013 -0800
15.3 @@ -0,0 +1,10 @@
15.4 +import shell;
15.5 +import import_enum_b.*;
15.6 +
15.7 +public main()
15.8 +{
15.9 + new Crab:crab = TotalCrab;
15.10 +
15.11 + shell.PrintNum(crab);
15.12 +}
15.13 +
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
16.2 +++ b/tests/basic/import_enum_b.sp Sun Jan 27 17:34:30 2013 -0800
16.3 @@ -0,0 +1,7 @@
16.4 +public enum Crab
16.5 +{
16.6 + A,
16.7 + B,
16.8 + TotalCrab
16.9 +};
16.10 +