├── test └── submod.cone ├── COPYRIGHT ├── src ├── c-compiler │ ├── ir │ │ ├── types │ │ │ ├── region.h │ │ │ ├── enum.h │ │ │ ├── typedef.h │ │ │ ├── void.h │ │ │ ├── enum.c │ │ │ ├── number.h │ │ │ ├── void.c │ │ │ ├── ttuple.h │ │ │ ├── typedef.c │ │ │ ├── pointer.h │ │ │ ├── arrayref.h │ │ │ ├── array.h │ │ │ ├── lifetime.h │ │ │ ├── pointer.c │ │ │ ├── permission.h │ │ │ ├── fnsig.h │ │ │ ├── number.c │ │ │ ├── ttuple.c │ │ │ ├── lifetime.c │ │ │ ├── region.c │ │ │ ├── reference.h │ │ │ ├── permission.c │ │ │ └── struct.h │ │ ├── exp │ │ │ ├── vtuple.h │ │ │ ├── arraylit.h │ │ │ ├── deref.h │ │ │ ├── allocate.h │ │ │ ├── sizeof.h │ │ │ ├── namedval.h │ │ │ ├── typelit.h │ │ │ ├── if.h │ │ │ ├── logic.h │ │ │ ├── assign.h │ │ │ ├── borrow.h │ │ │ ├── vtuple.c │ │ │ ├── sizeof.c │ │ │ ├── cast.h │ │ │ ├── namedval.c │ │ │ ├── deref.c │ │ │ ├── block.h │ │ │ ├── literal.h │ │ │ ├── logic.c │ │ │ ├── nameuse.h │ │ │ ├── fncall.h │ │ │ ├── allocate.c │ │ │ └── arraylit.c │ │ ├── stmt │ │ │ ├── continue.h │ │ │ ├── import.h │ │ │ ├── intrinsic.c │ │ │ ├── program.h │ │ │ ├── swap.h │ │ │ ├── return.h │ │ │ ├── const.h │ │ │ ├── fielddcl.h │ │ │ ├── break.h │ │ │ ├── module.h │ │ │ ├── import.c │ │ │ ├── intrinsic.h │ │ │ ├── fndcl.h │ │ │ ├── vardcl.h │ │ │ ├── continue.c │ │ │ ├── program.c │ │ │ ├── break.c │ │ │ ├── const.c │ │ │ ├── swap.c │ │ │ ├── fielddcl.c │ │ │ └── return.c │ │ ├── meta │ │ │ ├── genvardcl.h │ │ │ ├── generic.h │ │ │ ├── genvardcl.c │ │ │ ├── macro.h │ │ │ └── macro.c │ │ ├── namespace.h │ │ ├── nodelist.h │ │ ├── nodes.h │ │ ├── clone.h │ │ ├── typetbl.h │ │ ├── instype.h │ │ ├── nametbl.h │ │ ├── flow.h │ │ ├── name.c │ │ ├── nodelist.c │ │ ├── iexp.h │ │ ├── name.h │ │ ├── instype.c │ │ ├── itype.h │ │ ├── namespace.c │ │ ├── ir.h │ │ └── typetbl.c │ ├── shared │ │ ├── utf8.h │ │ ├── memory.h │ │ ├── timer.h │ │ ├── fileio.h │ │ ├── utf8.c │ │ ├── options.h │ │ ├── timer.c │ │ ├── error.c │ │ ├── memory.c │ │ └── error.h │ ├── corelib │ │ ├── corelib.h │ │ └── corelib.c │ ├── conec.h │ ├── coneopts.h │ ├── parser │ │ ├── parser.h │ │ └── parsehelper.c │ ├── genllvm │ │ └── genllvm.h │ └── conec.c └── conestd │ └── stdio.c ├── LICENSE ├── CONTRIBUTING.md └── PLAN.md /test/submod.cone: -------------------------------------------------------------------------------- 1 | // A test module in Cone that does nothing interesting 2 | 3 | fn inc(n i32) i32: 4 | n+1 5 | 6 | mut r = 9 7 | mut _rad = 10 8 | fn incr(): 9 | _rad=inc(r) 10 | -------------------------------------------------------------------------------- /COPYRIGHT: -------------------------------------------------------------------------------- 1 | Copyrights in Cone Programming Language are retained by their contributors. No 2 | copyright assignment is required to contribute to the project. 3 | 4 | Some files include explicit copyright notices and/or license notices. 5 | For full authorship information, see the version control history. 6 | 7 | Cone is licensed under the MIT license: 8 | or , at your option. -------------------------------------------------------------------------------- /src/c-compiler/ir/types/region.h: -------------------------------------------------------------------------------- 1 | /** region type handling. A region is a specialized struct 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #ifndef region_h 9 | #define region_h 10 | 11 | int isRegion(INode *region, Name *namesym); 12 | 13 | void regionAllocTypeCheck(INode *region); 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /src/c-compiler/ir/exp/vtuple.h: -------------------------------------------------------------------------------- 1 | /** Handling for value tuple nodes 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #ifndef vtuple_h 9 | #define vtuple_h 10 | 11 | // Note: the newTupleNode and cloneTupleNode are in ttuple.c 12 | 13 | // Serialize a value tuple node 14 | void vtuplePrint(TupleNode *tuple); 15 | 16 | // Type check the value tuple node 17 | // - Infer type tuple from types of vtuple's values 18 | void vtupleTypeCheck(TypeCheckState *pstate, TupleNode *node); 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /src/c-compiler/ir/exp/arraylit.h: -------------------------------------------------------------------------------- 1 | /** Handling for array literals 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #ifndef arraylit_h 9 | #define arraylit_h 10 | 11 | // Type check an array literal (used by region allocation only) 12 | void arrayLitTypeCheckDimExp(TypeCheckState *pstate, ArrayNode *arrlit); 13 | 14 | // Type check an array literal 15 | void arrayLitTypeCheck(TypeCheckState *pstate, ArrayNode *arrlit); 16 | 17 | // Is an array actually a literal? 18 | int arrayLitIsLiteral(ArrayNode *node); 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /src/c-compiler/ir/stmt/continue.h: -------------------------------------------------------------------------------- 1 | /** Handling for continue nodes 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #ifndef continue_h 9 | #define continue_h 10 | 11 | // Continue statements use the BreakRetNode structure defined in break.h 12 | 13 | BreakRetNode *newContinueNode(); 14 | 15 | // Clone continue 16 | INode *cloneContinueNode(CloneState *cstate, BreakRetNode *node); 17 | 18 | // Name resolution for continue 19 | void continueNameRes(NameResState *pstate, BreakRetNode *node); 20 | void continueTypeCheck(TypeCheckState *pstate, BreakRetNode *node); 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /src/c-compiler/ir/exp/deref.h: -------------------------------------------------------------------------------- 1 | /** Handling for deref nodes 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #ifndef deref_h 9 | #define deref_h 10 | 11 | // The definition of StarNode etc. is in pointer.h 12 | 13 | void derefPrint(StarNode *node); 14 | 15 | // Type check deref node 16 | void derefTypeCheck(TypeCheckState *pstate, StarNode *node); 17 | 18 | // Inject automatic deref node, if node's type is a ref or ptr. Return 1 if dereffed. 19 | int derefInject(INode **node); 20 | 21 | // Perform data flow analysis on deref node 22 | void derefFlow(FlowState *fstate, StarNode **node); 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /src/c-compiler/ir/exp/allocate.h: -------------------------------------------------------------------------------- 1 | /** Handling for allocate expression nodes 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #ifndef allocate_h 9 | #define allocate_h 10 | 11 | // Uses RefNode from reference.h 12 | 13 | void allocatePrint(RefNode *node); 14 | 15 | // Name resolution for questag: decide if Option type or fold into AllocNode 16 | void allocateQuesNameRes(NameResState *pstate, FnCallNode **nodep); 17 | 18 | // Type check allocate node 19 | void allocateTypeCheck(TypeCheckState *pstate, RefNode **node); 20 | 21 | // Perform data flow analysis on addr node 22 | void allocateFlow(FlowState *fstate, RefNode **nodep); 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /src/c-compiler/ir/stmt/import.h: -------------------------------------------------------------------------------- 1 | /** import statement node and helper functions 2 | * 3 | * @file 4 | * 5 | * This source file is part of the Cone Programming Language C compiler 6 | * See Copyright Notice in conec.h 7 | */ 8 | 9 | #ifndef import_h 10 | #define import_h 11 | 12 | // Module is the envelope for all modules for the compiled program 13 | typedef struct { 14 | INodeHdr; 15 | ModuleNode *module; 16 | int foldall; // was "*" specified? 17 | } ImportNode; 18 | 19 | // Create a new Import node 20 | ImportNode *newImportNode(); 21 | 22 | void importPrint(ImportNode *pgm); 23 | 24 | void importNameRes(NameResState *pstate, ImportNode *mod); 25 | 26 | void importTypeCheck(TypeCheckState *pstate, ImportNode *mod); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /src/c-compiler/ir/types/enum.h: -------------------------------------------------------------------------------- 1 | /** Enumerated values/types 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #ifndef enum_h 9 | #define enum_h 10 | 11 | // Lifetime type info 12 | typedef struct EnumNode { 13 | INsTypeNodeHdr; 14 | Name *namesym; 15 | uint8_t bytes; 16 | } EnumNode; 17 | 18 | // Create a new enum declaration node 19 | EnumNode *newEnumNode(); 20 | 21 | // Serialize an enum node 22 | void enumPrint(EnumNode *node); 23 | 24 | // Name resolution of an enum type 25 | void enumNameRes(NameResState *pstate, EnumNode *node); 26 | 27 | // Type check an enum type 28 | void enumTypeCheck(TypeCheckState *pstate, EnumNode *node); 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /src/c-compiler/ir/exp/sizeof.h: -------------------------------------------------------------------------------- 1 | /** Handling for sizeof nodes 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #ifndef sizeof_h 9 | #define sizeof_h 10 | 11 | // Get size of a type 12 | typedef struct SizeofNode { 13 | IExpNodeHdr; 14 | INode *type; 15 | } SizeofNode; 16 | 17 | SizeofNode *newSizeofNode(); 18 | 19 | // Clone sizeof 20 | INode *cloneSizeofNode(CloneState *cstate, SizeofNode *node); 21 | 22 | void sizeofPrint(SizeofNode *node); 23 | 24 | // Name resolution of sizeof node 25 | void sizeofNameRes(NameResState *pstate, SizeofNode *node); 26 | 27 | // Type check sizeof node 28 | void sizeofTypeCheck(TypeCheckState *pstate, SizeofNode *node); 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /src/c-compiler/ir/stmt/intrinsic.c: -------------------------------------------------------------------------------- 1 | /** Handling for intrinsic nodes 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #include "../ir.h" 9 | 10 | // Create a new intrinsic node 11 | IntrinsicNode *newIntrinsicNode(int16_t intrinsic) { 12 | IntrinsicNode *intrinsicNode; 13 | newNode(intrinsicNode, IntrinsicNode, IntrinsicTag); 14 | intrinsicNode->intrinsicFn = intrinsic; 15 | return intrinsicNode; 16 | } 17 | 18 | // Serialize an intrinsic node 19 | void intrinsicPrint(IntrinsicNode *intrinsicNode) { 20 | inodeFprint("intrinsic function"); 21 | } 22 | 23 | // Check the intrinsic node 24 | void intrinsicPass(TypeCheckState *pstate, IntrinsicNode *intrinsicNode) { 25 | } 26 | -------------------------------------------------------------------------------- /src/c-compiler/ir/types/typedef.h: -------------------------------------------------------------------------------- 1 | /** Handling for typedef declaration nodes 2 | * 3 | * This source file is part of the Cone Programming Language C compiler 4 | * See Copyright Notice in conec.h 5 | */ 6 | 7 | #ifndef typedef_h 8 | #define typedef_h 9 | 10 | // Generic variable declaration node 11 | typedef struct TypedefNode { 12 | ITypeNodeHdr; 13 | Name *namesym; 14 | INode *typeval; 15 | } TypedefNode; 16 | 17 | // Create a new typedef node 18 | TypedefNode *newTypedefNode(Name *namesym); 19 | 20 | void typedefPrint(TypedefNode *var); 21 | 22 | // Name resolution 23 | void typedefNameRes(NameResState *pstate, TypedefNode *var); 24 | 25 | // Type check generic variable declaration 26 | void typedefTypeCheck(TypeCheckState *pstate, TypedefNode *var); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /src/c-compiler/ir/types/void.h: -------------------------------------------------------------------------------- 1 | /** void type (e.g., function that returns no value) 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #ifndef void_h 9 | #define void_h 10 | 11 | // Void type - e.g., for fn with no return value 12 | typedef struct VoidTypeNode { 13 | INodeHdr; 14 | } VoidTypeNode; 15 | 16 | // Unique, unclonable node that marks the absence of something 17 | typedef struct AbsenceNode { 18 | IExpNodeHdr; 19 | } AbsenceNode; 20 | 21 | VoidTypeNode *newVoidNode(); 22 | 23 | // Clone void 24 | INode *cloneVoidNode(CloneState *cstate, VoidTypeNode *node); 25 | 26 | void voidPrint(VoidTypeNode *voidnode); 27 | 28 | // Create a new Absence node 29 | AbsenceNode *newAbsenceNode(); 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /src/c-compiler/shared/utf8.h: -------------------------------------------------------------------------------- 1 | /** UTF-8 helper routines 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #ifndef utf8_h 9 | #define utf8_h 10 | 11 | #include 12 | 13 | // Evalutes non-zero if UTF8 code takes more than one byte 14 | #define utf8IsMultibyte(src) (*(src)&0x80) 15 | 16 | // Evaluates to how many bytes to skip over to next UTF8 character 17 | // Note that we won't skip past end-of-string 18 | #define utf8ByteSkip(src) (\ 19 | (*(src) & 0xF0) == 0xF0? 4 : \ 20 | (*(src) & 0xE0) == 0xE0? 3 : \ 21 | (*(src) & 0xC0) == 0xC0? 2 : \ 22 | (*(src) == '\0' || *(src) == '\x1A')? 0 : 1) 23 | 24 | uint32_t utf8GetCode(const char *src); 25 | int utf8IsLetter(const char* srcp); 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /src/c-compiler/ir/exp/namedval.h: -------------------------------------------------------------------------------- 1 | /** Handling for named value nodes 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #ifndef namedval_h 9 | #define namedval_h 10 | 11 | // Cast to another type 12 | typedef struct NamedValNode { 13 | IExpNodeHdr; 14 | INode *name; 15 | INode *val; 16 | } NamedValNode; 17 | 18 | NamedValNode *newNamedValNode(INode *name); 19 | 20 | // Clone namedval 21 | INode *cloneNamedValNode(CloneState *cstate, NamedValNode *node); 22 | 23 | void namedValPrint(NamedValNode *node); 24 | 25 | // Name resolution of named value node 26 | void namedValNameRes(NameResState *pstate, NamedValNode *node); 27 | 28 | // Type check named value node 29 | void namedValTypeCheck(TypeCheckState *pstate, NamedValNode *node); 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /src/c-compiler/ir/meta/genvardcl.h: -------------------------------------------------------------------------------- 1 | /** Handling for generic variable declaration nodes 2 | * 3 | * This source file is part of the Cone Programming Language C compiler 4 | * See Copyright Notice in conec.h 5 | */ 6 | 7 | #ifndef genvardcl_h 8 | #define genvardcl_h 9 | 10 | // Generic variable declaration node 11 | typedef struct GenVarDclNode { 12 | IExpNodeHdr; // 'vtype': type of this name's value 13 | Name *namesym; 14 | } GenVarDclNode; 15 | 16 | // Create a new generic variable declaraction node 17 | GenVarDclNode *newGVarDclNode(Name *namesym); 18 | 19 | void gVarDclPrint(GenVarDclNode *var); 20 | 21 | // Name resolution 22 | void gVarDclNameRes(NameResState *pstate, GenVarDclNode *var); 23 | 24 | // Type check generic variable declaration 25 | void gVarDclTypeCheck(TypeCheckState *pstate, GenVarDclNode *var); 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /src/c-compiler/ir/types/enum.c: -------------------------------------------------------------------------------- 1 | /** Enumerated values/types 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #include "../ir.h" 9 | 10 | // Create a new enum declaration node 11 | EnumNode *newEnumNode() { 12 | EnumNode *node; 13 | newNode(node, EnumNode, EnumTag); 14 | node->bytes = 1; 15 | node->namesym = anonName; 16 | node->llvmtype = NULL; 17 | iNsTypeInit((INsTypeNode*)node, 8); 18 | return node; 19 | } 20 | 21 | // Serialize a lifetime node 22 | void enumPrint(EnumNode *node) { 23 | inodeFprint("enum "); 24 | } 25 | 26 | // Name resolution of an enum type 27 | void enumNameRes(NameResState *pstate, EnumNode *node) { 28 | } 29 | 30 | // Type check an enum type 31 | void enumTypeCheck(TypeCheckState *pstate, EnumNode *node) { 32 | } 33 | -------------------------------------------------------------------------------- /src/c-compiler/ir/stmt/program.h: -------------------------------------------------------------------------------- 1 | /** Program structure and helper functions 2 | * 3 | * @file 4 | * 5 | * This source file is part of the Cone Programming Language C compiler 6 | * See Copyright Notice in conec.h 7 | */ 8 | 9 | #ifndef program_h 10 | #define program_h 11 | 12 | // Module is the envelope for all modules for the compiled program 13 | typedef struct { 14 | INodeHdr; 15 | Nodes *modules; 16 | } ProgramNode; 17 | 18 | ProgramNode *newProgramNode(); 19 | void pgmPrint(ProgramNode *pgm); 20 | 21 | // Find an already parsed module, or return NULL if not found 22 | ModuleNode *pgmFindMod(ProgramNode *pgm, Name *modname); 23 | 24 | // Add a new module to the program 25 | ModuleNode *pgmAddMod(ProgramNode *pgm, int16_t flags); 26 | 27 | void pgmNameRes(NameResState *pstate, ProgramNode *mod); 28 | 29 | void pgmTypeCheck(TypeCheckState *pstate, ProgramNode *mod); 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /src/c-compiler/ir/stmt/swap.h: -------------------------------------------------------------------------------- 1 | /** Handling for swap nodes 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #ifndef swap_h 9 | #define swap_h 10 | 11 | // Swap node 12 | typedef struct { 13 | INodeHdr; 14 | INode *lval; 15 | INode *rval; 16 | } SwapNode; 17 | 18 | SwapNode *newSwapNode(INode *lval, INode *rval); 19 | 20 | // Clone assign 21 | INode *cloneSwapNode(CloneState *cstate, SwapNode *node); 22 | 23 | void swapPrint(SwapNode *node); 24 | 25 | // Name resolution for assignment node 26 | void swapNameRes(NameResState *pstate, SwapNode *node); 27 | 28 | // Type check for assignment node 29 | void swapTypeCheck(TypeCheckState *pstate, SwapNode *node); 30 | 31 | // Perform data flow analysis on assignment node 32 | void swapFlow(FlowState *fstate, SwapNode **node); 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /src/c-compiler/shared/memory.h: -------------------------------------------------------------------------------- 1 | /** Memory management 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #ifndef memory_h 9 | #define memory_h 10 | 11 | #include 12 | #include 13 | 14 | // Configurable size for arenas (specify as multiples of 4096 byte pages) 15 | extern size_t gMemBlkArenaSize; // Default is 256 pages 16 | extern size_t gMemStrArenaSize; // Default is 128 pages 17 | 18 | // Allocate memory for a block, aligned to a 16-byte boundary 19 | void *memAllocBlk(size_t size); 20 | 21 | // Allocate memory for a string and copy contents over, if not NULL 22 | // Allocates extra byte for string-ending 0, appending it to copied string 23 | char *memAllocStr(char *str, size_t size); 24 | 25 | // Return memory allocated and used 26 | size_t memUsed(); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /src/c-compiler/ir/exp/typelit.h: -------------------------------------------------------------------------------- 1 | /** Handling for type literals 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #ifndef list_h 9 | #define list_h 10 | 11 | // Serialize a type literal 12 | void typeLitPrint(FnCallNode *node); 13 | 14 | // Name resolution of the literal node 15 | void typeLitNameRes(NameResState *pstate, FnCallNode *lit); 16 | 17 | // Reorder the literal's field values to the same order as the type's fields 18 | // Also prevent the specification of a value for a private field outside the type's methods 19 | int typeLitStructReorder(FnCallNode *arrlit, StructNode *strnode, int private); 20 | 21 | // Check the type literal node 22 | void typeLitTypeCheck(TypeCheckState *pstate, FnCallNode *lit); 23 | 24 | // Is the type literal actually a literal? 25 | int typeLitIsLiteral(FnCallNode *node); 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /src/c-compiler/ir/meta/generic.h: -------------------------------------------------------------------------------- 1 | /** Handling for generic nodes (also used for macros) 2 | * 3 | * This source file is part of the Cone Programming Language C compiler 4 | * See Copyright Notice in conec.h 5 | */ 6 | 7 | #ifndef generic_h 8 | #define generic_h 9 | 10 | typedef struct GenericInfo { 11 | Nodes *parms; // Declared parameter nodes w/ defaults (GenVarTag) 12 | Nodes *memonodes; // Pairs of memoized generic calls and cloned bodies 13 | } GenericInfo; 14 | 15 | // Create a new generic info block 16 | GenericInfo *newGenericInfo(); 17 | 18 | // Serialize 19 | void genericInfoPrint(GenericInfo *info); 20 | 21 | // Perform generic substitution, if this is a correctly set up generic "fncall" 22 | // Return 1 if done/error needed. Return 0 if not generic or it leaves behind a lit/fncall that needs processing. 23 | int genericSubstitute(TypeCheckState *pstate, FnCallNode **nodep); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /src/c-compiler/shared/timer.h: -------------------------------------------------------------------------------- 1 | /** Timer handling 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #ifndef timer_h 9 | #define timer_h 10 | 11 | #include 12 | #include 13 | 14 | enum Timers { 15 | LoadTimer, 16 | LexTimer, 17 | ParseTimer, 18 | SemTimer, 19 | GenTimer, 20 | VerifyTimer, 21 | OptTimer, 22 | CodeGenTimer, 23 | SetupTimer, 24 | TimerCount 25 | }; 26 | 27 | // Start timing ticks for a specific timer 28 | void timerBegin(size_t aTimer); 29 | 30 | // Get the tick count for a timer 31 | uint64_t timerGetTicks(size_t aTimer); 32 | 33 | // Get a specific timer in seconds 34 | double timerGetSecs(size_t aTimer); 35 | 36 | // Get the summary of all timers in seconds 37 | double timerSummary(); 38 | 39 | // Print out all timers 40 | void timerPrint(); 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /src/c-compiler/ir/types/number.h: -------------------------------------------------------------------------------- 1 | /** Handling for primitive numbers 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #ifndef number_h 9 | #define number_h 10 | 11 | // For primitives such as integer, unsigned integet, floats 12 | typedef struct NbrNode { 13 | INsTypeNodeHdr; 14 | Name *namesym; 15 | unsigned char bits; // e.g., int32 uses 32 bits 16 | } NbrNode; 17 | 18 | // Clone number node 19 | INode *cloneNbrNode(CloneState *cstate, NbrNode *node); 20 | 21 | void nbrTypePrint(NbrNode *node); 22 | int isNbr(INode *node); 23 | 24 | // Return a type that is the supertype of both type nodes, or NULL if none found 25 | INode *nbrFindSuper(INode *type1, INode *type2); 26 | 27 | // Is from-type a subtype of to-struct (we know they are not the same) 28 | TypeCompare nbrMatches(INode *totype, INode *fromtype, SubtypeConstraint constraint); 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /src/c-compiler/ir/stmt/return.h: -------------------------------------------------------------------------------- 1 | /** Handling for return nodes 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #ifndef return_h 9 | #define return_h 10 | 11 | // Return statements use the BreakRetNode structure defined in break.h 12 | 13 | BreakRetNode *newReturnNode(); 14 | BreakRetNode *newReturnNodeExp(INode *exp); 15 | 16 | // Clone return 17 | INode *cloneReturnNode(CloneState *cstate, BreakRetNode *node); 18 | 19 | void returnPrint(BreakRetNode *node); 20 | // Name resolution for return 21 | void returnNameRes(NameResState *pstate, BreakRetNode *node); 22 | 23 | // Type check for return statement 24 | // Related analysis for return elsewhere: 25 | // - Block ensures that return can only appear at end of block 26 | // - NameDcl turns fn block's final expression into an implicit return 27 | void returnTypeCheck(TypeCheckState *pstate, BreakRetNode *node); 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /src/c-compiler/ir/meta/genvardcl.c: -------------------------------------------------------------------------------- 1 | /** Handling for generic variable declaration nodes 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #include "../ir.h" 9 | 10 | #include 11 | #include 12 | 13 | // Create a new generic variable declaraction node 14 | GenVarDclNode *newGVarDclNode(Name *namesym) { 15 | GenVarDclNode *var; 16 | newNode(var, GenVarDclNode, GenVarDclTag); 17 | var->vtype = NULL; 18 | var->namesym = namesym; 19 | return var; 20 | } 21 | 22 | // Serialize a generic variable node 23 | void gVarDclPrint(GenVarDclNode *name) { 24 | inodeFprint("%s", &name->namesym->namestr); 25 | } 26 | 27 | // Perform name resolution 28 | void gVarDclNameRes(NameResState *pstate, GenVarDclNode *var) { 29 | nametblHookNode(var->namesym, (INode*)var); 30 | } 31 | 32 | // Type check 33 | void gVarDclTypeCheck(TypeCheckState *pstate, GenVarDclNode *var) { 34 | } 35 | -------------------------------------------------------------------------------- /src/c-compiler/shared/fileio.h: -------------------------------------------------------------------------------- 1 | /** File i/o 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #ifndef fileio_h 9 | #define fileio_h 10 | 11 | extern char **fileSearchPaths; 12 | 13 | // Load a file into an allocated string, return pointer or NULL if not found 14 | char *fileLoad(char *fn); 15 | 16 | // Extract a filename only (no extension) from a path 17 | char *fileName(char *fn); 18 | 19 | // Concatenate folder, filename and extension into a path 20 | char *fileMakePath(char *dir, char *srcfn, char *ext); 21 | 22 | // Create a new source file url relative to current, substituting new path and .cone extension 23 | char *fileSrcUrl(char *cururl, char *srcfn, int newfolder); 24 | 25 | // Load source file, where srcfn is relative to cururl 26 | // - Look at fn+.cone or fn+/mod.cone 27 | // - return full pathname for source file 28 | char *fileLoadSrc(char *cururl, char *srcfn, char **fn); 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /src/c-compiler/ir/stmt/const.h: -------------------------------------------------------------------------------- 1 | /** Handling for const declaration nodes 2 | * 3 | * This source file is part of the Cone Programming Language C compiler 4 | * See Copyright Notice in conec.h 5 | */ 6 | 7 | #ifndef const_h 8 | #define const_h 9 | 10 | // Variable declaration node (global, local, parm) 11 | typedef struct ConstDclNode { 12 | IExpNodeHdr; // 'vtype': type of this name's value 13 | Name *namesym; 14 | INode *value; // Starting value/declaration (NULL if not initialized) 15 | } ConstDclNode; 16 | 17 | ConstDclNode *newConstDclNode(Name *namesym); 18 | 19 | // Create a new variable dcl node that is a copy of an existing one 20 | INode *cloneConstDclNode(CloneState *cstate, ConstDclNode *node); 21 | 22 | void constDclPrint(ConstDclNode *fn); 23 | 24 | // Name resolution of vardcl 25 | void constDclNameRes(NameResState *pstate, ConstDclNode *node); 26 | 27 | // Type check vardcl 28 | void constDclTypeCheck(TypeCheckState *pstate, ConstDclNode *node); 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /src/c-compiler/ir/exp/if.h: -------------------------------------------------------------------------------- 1 | /** Handling for if nodes 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #ifndef if_h 9 | #define if_h 10 | 11 | // If statement 12 | typedef struct IfNode { 13 | IExpNodeHdr; 14 | Nodes *condblk; 15 | } IfNode; 16 | 17 | IfNode *newIfNode(); 18 | 19 | // Clone if 20 | INode *cloneIfNode(CloneState *cstate, IfNode *node); 21 | 22 | void ifPrint(IfNode *ifnode); 23 | 24 | // if node name resolution 25 | void ifNameRes(NameResState *pstate, IfNode *ifnode); 26 | 27 | // Type check the if statement node 28 | // - Every conditional expression must be a bool 29 | // - if's vtype is specified/checked only when coerced by iexpCoerces 30 | void ifTypeCheck(TypeCheckState *pstate, IfNode *ifnode, INode *expectType); 31 | 32 | void ifRemoveReturns(IfNode *ifnode); 33 | 34 | // Perform data flow analysis on an if expression 35 | void ifFlow(FlowState *fstate, IfNode **ifnodep); 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /src/c-compiler/ir/exp/logic.h: -------------------------------------------------------------------------------- 1 | /** Handling for logic nodes 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #ifndef logic_h 9 | #define logic_h 10 | 11 | // Logic operator: not, or, and 12 | typedef struct LogicNode { 13 | IExpNodeHdr; 14 | INode *lexp; 15 | INode *rexp; 16 | } LogicNode; 17 | 18 | LogicNode *newLogicNode(int16_t typ); 19 | 20 | // Clone logic node 21 | INode *cloneLogicNode(CloneState *cstate, LogicNode *node); 22 | 23 | void logicPrint(LogicNode *node); 24 | 25 | // Name resolution of not logic node 26 | void logicNotNameRes(NameResState *pstate, LogicNode *node); 27 | 28 | // Type check not logic node 29 | void logicNotTypeCheck(TypeCheckState *pstate, LogicNode *node); 30 | 31 | // Name resolution of logic node 32 | void logicNameRes(NameResState *pstate, LogicNode *node); 33 | 34 | // Type check logic node 35 | void logicTypeCheck(TypeCheckState *pstate, LogicNode *node); 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /src/c-compiler/ir/types/void.c: -------------------------------------------------------------------------------- 1 | /** void type 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #include "../ir.h" 9 | 10 | // Create a new Void type node 11 | VoidTypeNode *newVoidNode() { 12 | VoidTypeNode *voidnode; 13 | newNode(voidnode, VoidTypeNode, VoidTag); 14 | voidnode->flags |= ZeroSizeType; 15 | return voidnode; 16 | } 17 | 18 | // Clone void 19 | INode *cloneVoidNode(CloneState *cstate, VoidTypeNode *node) { 20 | StarNode *newnode = memAllocBlk(sizeof(VoidTypeNode)); 21 | memcpy(newnode, node, sizeof(VoidTypeNode)); 22 | return (INode *)newnode; 23 | } 24 | 25 | // Create a new Absence node 26 | AbsenceNode *newAbsenceNode() { 27 | AbsenceNode *node; 28 | newNode(node, AbsenceNode, AbsenceTag); 29 | node->vtype = (INode*)newVoidNode(); 30 | return node; 31 | } 32 | 33 | // Serialize the void type node 34 | void voidPrint(VoidTypeNode *voidnode) { 35 | inodeFprint("void"); 36 | } 37 | -------------------------------------------------------------------------------- /src/c-compiler/ir/types/ttuple.h: -------------------------------------------------------------------------------- 1 | /** Handling for type tuple nodes 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #ifndef ttuple_h 9 | #define ttuple_h 10 | 11 | // A tuple is a comma-separated list of elements, each different. 12 | // This structure supports both type tuples and tuple literals. 13 | typedef struct { 14 | ITypeNodeHdr; 15 | Nodes *elems; 16 | } TupleNode; 17 | 18 | // Create a new type tuple node 19 | TupleNode *newTupleNode(int cnt); 20 | 21 | // Clone tuple 22 | INode *cloneTupleNode(CloneState *cstate, TupleNode *node); 23 | 24 | // Serialize a type tuple node 25 | void ttuplePrint(TupleNode *tuple); 26 | 27 | // Name resolution of type tuple node 28 | void ttupleNameRes(NameResState *pstate, TupleNode *node); 29 | 30 | // Type check type tuple node 31 | void ttupleTypeCheck(TypeCheckState *pstate, TupleNode *node); 32 | 33 | // Compare that two tuples are equivalent 34 | int ttupleEqual(TupleNode *totype, TupleNode *fromtype); 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /src/c-compiler/ir/types/typedef.c: -------------------------------------------------------------------------------- 1 | /** Handling for typedef declaration nodes 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #include "../ir.h" 9 | 10 | #include 11 | #include 12 | 13 | // Create a new typedef declaraction node 14 | TypedefNode *newTypedefNode(Name *namesym) { 15 | TypedefNode *var; 16 | newNode(var, TypedefNode, TypedefTag); 17 | var->typeval = NULL; 18 | var->namesym = namesym; 19 | return var; 20 | } 21 | 22 | // Serialize a typedef node 23 | void typedefPrint(TypedefNode *name) { 24 | inodeFprint("typedef %s ", &name->namesym->namestr); 25 | inodePrintNode(name->typeval); 26 | } 27 | 28 | // Perform name resolution 29 | void typedefNameRes(NameResState *pstate, TypedefNode *var) { 30 | inodeNameRes(pstate, &var->typeval); 31 | nametblHookNode(var->namesym, (INode*)var); 32 | } 33 | 34 | // Type check 35 | void typedefTypeCheck(TypeCheckState *pstate, TypedefNode *var) { 36 | itypeTypeCheck(pstate, &var->typeval); 37 | } 38 | -------------------------------------------------------------------------------- /src/c-compiler/ir/exp/assign.h: -------------------------------------------------------------------------------- 1 | /** Handling for assignment nodes 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #ifndef assign_h 9 | #define assign_h 10 | 11 | // Variations on assignment 12 | enum AssignType { 13 | NormalAssign, 14 | LeftAssign 15 | }; 16 | 17 | // Assignment node 18 | typedef struct AssignNode { 19 | IExpNodeHdr; 20 | INode *lval; 21 | INode *rval; 22 | int16_t assignType; 23 | } AssignNode; 24 | 25 | AssignNode *newAssignNode(int16_t assigntype, INode *lval, INode *rval); 26 | 27 | // Clone assign 28 | INode *cloneAssignNode(CloneState *cstate, AssignNode *node); 29 | 30 | void assignPrint(AssignNode *node); 31 | 32 | // Name resolution for assignment node 33 | void assignNameRes(NameResState *pstate, AssignNode *node); 34 | 35 | // Type check for assignment node 36 | void assignTypeCheck(TypeCheckState *pstate, AssignNode *node); 37 | 38 | // Perform data flow analysis on assignment node 39 | void assignFlow(FlowState *fstate, AssignNode **node); 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /src/c-compiler/ir/exp/borrow.h: -------------------------------------------------------------------------------- 1 | /** Handling for borrow expression nodes 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #ifndef borrow_h 9 | #define borrow_h 10 | 11 | // Uses RefNode defined in reference.h 12 | 13 | // Create a borrowed ref node 14 | INode *newBorrowMutRef(INode *node, INode* type, INode *perm); 15 | 16 | // Inject a borrow mutable node on some node (expected to be an lval) 17 | void borrowMutRef(INode **node, INode* type, INode *perm); 18 | 19 | // Auto-inject a borrow note in front of 'from', to create totypedcl type 20 | void borrowAuto(INode **from, INode *totypedcl); 21 | 22 | // Can we safely auto-borrow to match expected type? 23 | // Note: totype has already done GetTypeDcl 24 | int borrowAutoMatches(INode *from, RefNode *totype); 25 | 26 | void borrowPrint(RefNode *node); 27 | 28 | // Type check borrow node 29 | void borrowTypeCheck(TypeCheckState *pstate, RefNode **node); 30 | 31 | // Perform data flow analysis on addr node 32 | void borrowFlow(FlowState *fstate, RefNode **nodep); 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /src/c-compiler/shared/utf8.c: -------------------------------------------------------------------------------- 1 | /** UTF8 Helper routines 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #include "utf8.h" 9 | #include 10 | 11 | /** Return the current unicode character whose UTF-8 bytes start at lex->bytepos */ 12 | uint32_t utf8GetCode(const char *src) { 13 | int nbytes; 14 | uint32_t chr; 15 | 16 | // Get info from first UTF-8 byte 17 | if ((*src&0xF0) == 0xF0) {nbytes=4; chr = *src&0x07;} 18 | else if ((*src&0xE0) == 0xE0) {nbytes=3; chr = *src&0x0F;} 19 | else if ((*src&0xC0) == 0xC0) {nbytes=2; chr = *src&0x1F;} 20 | else if ((*src&0x80) == 0x00) {nbytes=1; chr = *src&0x7F;} 21 | else {nbytes=1; chr = 0;} // error 22 | 23 | // Obtain remaining bytes 24 | while (--nbytes) { 25 | src++; 26 | if ((*src&0xC0)==0x80) 27 | chr = (chr<<6) + (*src&0x3F); 28 | } 29 | return chr; 30 | } 31 | 32 | // Return true if unicode is a letter 33 | int utf8IsLetter(const char* srcp) { 34 | return utf8IsMultibyte(srcp) || isalpha(*srcp); 35 | } 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017-2020 Jonathan Goodwin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/c-compiler/ir/exp/vtuple.c: -------------------------------------------------------------------------------- 1 | /** Handling for value tuple nodes 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #include "../ir.h" 9 | 10 | // Serialize a value tuple node 11 | void vtuplePrint(TupleNode *tuple) { 12 | INode **nodesp; 13 | uint32_t cnt; 14 | 15 | for (nodesFor(tuple->elems, cnt, nodesp)) { 16 | inodePrintNode(*nodesp); 17 | if (cnt) 18 | inodeFprint(","); 19 | } 20 | } 21 | 22 | // Type check the value tuple node 23 | // - Infer type tuple from types of vtuple's values 24 | void vtupleTypeCheck(TypeCheckState *pstate, TupleNode *tuple) { 25 | // Build ad hoc type tuple that accumulates types of vtuple's values 26 | TupleNode *ttuple = newTupleNode(tuple->elems->used); 27 | ttuple->tag = TTupleTag; 28 | tuple->vtype = (INode *)ttuple; 29 | INode **nodesp; 30 | uint32_t cnt; 31 | for (nodesFor(tuple->elems, cnt, nodesp)) { 32 | if (iexpTypeCheckAny(pstate, nodesp) == 0) 33 | continue; 34 | nodesAdd(&ttuple->elems, ((IExpNode *)*nodesp)->vtype); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/c-compiler/ir/types/pointer.h: -------------------------------------------------------------------------------- 1 | /** Handling for pointer types 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #ifndef pointer_h 9 | #define pointer_h 10 | 11 | // For pointer or deref nodes 12 | typedef struct { 13 | ITypeNodeHdr; 14 | INode *vtexp; // Value type 15 | } StarNode; 16 | 17 | // Create a new "star" node (ptr type or deref exp) whose vtexp will be filled in later 18 | StarNode *newStarNode(uint16_t tag); 19 | 20 | // Clone ptr or deref node 21 | INode *cloneStarNode(CloneState *cstate, StarNode *node); 22 | 23 | // Serialize a pointer type 24 | void ptrPrint(StarNode *node); 25 | 26 | // Name resolution of a pointer type 27 | void ptrNameRes(NameResState *pstate, StarNode *node); 28 | 29 | // Type check a pointer type 30 | void ptrTypeCheck(TypeCheckState *pstate, StarNode *name); 31 | 32 | // Compare two pointer signatures to see if they are equivalent 33 | int ptrEqual(StarNode *node1, StarNode *node2); 34 | 35 | // Will from pointer coerce to a to pointer (we know they are not the same) 36 | TypeCompare ptrMatches(StarNode *to, StarNode *from, SubtypeConstraint constraint); 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /src/c-compiler/ir/stmt/fielddcl.h: -------------------------------------------------------------------------------- 1 | /** Handling for field declaration nodes 2 | * 3 | * This source file is part of the Cone Programming Language C compiler 4 | * See Copyright Notice in conec.h 5 | */ 6 | 7 | #ifndef fielddcl_h 8 | #define fielddcl_h 9 | 10 | // Field declaration node 11 | typedef struct FieldDclNode { 12 | IExpNodeHdr; // 'vtype': field's type 13 | Name *namesym; 14 | INode *value; // Default value (NULL if not initialized) 15 | INode *perm; // Permission type (often mut or imm) 16 | uint16_t index; // field's index within the type 17 | uint16_t vtblidx; // field's index within the type's vtable 18 | } FieldDclNode; 19 | 20 | 21 | FieldDclNode *newFieldDclNode(Name *namesym, INode *perm); 22 | 23 | // Create a new field node that is a copy of an existing one 24 | INode *cloneFieldDclNode(CloneState *cstate, FieldDclNode *node); 25 | 26 | void fieldDclPrint(FieldDclNode *fn); 27 | 28 | // Name resolution of field declaration 29 | void fieldDclNameRes(NameResState *pstate, FieldDclNode *node); 30 | 31 | // Type check field declaration 32 | void fieldDclTypeCheck(TypeCheckState *pstate, FieldDclNode *node); 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /src/c-compiler/ir/meta/macro.h: -------------------------------------------------------------------------------- 1 | /** Handling for generic nodes (also used for macros) 2 | * 3 | * This source file is part of the Cone Programming Language C compiler 4 | * See Copyright Notice in conec.h 5 | */ 6 | 7 | #ifndef macro_h 8 | #define macro_h 9 | 10 | // Macro declaration node 11 | typedef struct MacroDclNode { 12 | IExpNodeHdr; // 'vtype': type of this name's value 13 | Name *namesym; 14 | Nodes *parms; // Declared parameter nodes w/ defaults (GenVarTag) 15 | INode *body; // The body of the generic 16 | Nodes *memonodes; // Pairs of memoized generic calls and cloned bodies 17 | } MacroDclNode; 18 | 19 | // Create a new macro declaraction node 20 | MacroDclNode *newMacroDclNode(Name *namesym); 21 | 22 | void macroPrint(MacroDclNode *fn); 23 | 24 | // Name resolution 25 | void macroNameRes(NameResState *pstate, MacroDclNode *node); 26 | 27 | // Type check generic 28 | void macroTypeCheck(TypeCheckState *pstate, MacroDclNode *node); 29 | 30 | // Type check generic name use 31 | void macroNameTypeCheck(TypeCheckState *pstate, NameUseNode **macro); 32 | 33 | // Instantiate a generic using passed arguments 34 | void macroCallTypeCheck(TypeCheckState *pstate, FnCallNode **nodep); 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /src/c-compiler/ir/exp/sizeof.c: -------------------------------------------------------------------------------- 1 | /** Handling for size-of nodes 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #include "../ir.h" 9 | 10 | // Create a new sizeof node 11 | SizeofNode *newSizeofNode() { 12 | SizeofNode *node; 13 | newNode(node, SizeofNode, SizeofTag); 14 | node->vtype = (INode*)usizeType; 15 | return node; 16 | } 17 | 18 | // Clone sizeof 19 | INode *cloneSizeofNode(CloneState *cstate, SizeofNode *node) { 20 | SizeofNode *newnode; 21 | newnode = memAllocBlk(sizeof(SizeofNode)); 22 | memcpy(newnode, node, sizeof(SizeofNode)); 23 | newnode->type = cloneNode(cstate, node->type); 24 | return (INode *)newnode; 25 | } 26 | 27 | // Serialize sizeof 28 | void sizeofPrint(SizeofNode *node) { 29 | inodeFprint("(sizeof, "); 30 | inodePrintNode(node->type); 31 | inodeFprint(")"); 32 | } 33 | 34 | // Name resolution of sizeof node 35 | void sizeofNameRes(NameResState *pstate, SizeofNode *node) { 36 | inodeNameRes(pstate, &node->type); 37 | } 38 | 39 | // Type check sizeof node 40 | void sizeofTypeCheck(TypeCheckState *pstate, SizeofNode *node) { 41 | if (itypeTypeCheck(pstate, &node->type) == 0) 42 | return; 43 | } 44 | -------------------------------------------------------------------------------- /src/conestd/stdio.c: -------------------------------------------------------------------------------- 1 | /** stdio - Standard library i/o 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | void printStr(char *p, size_t len) { 13 | fwrite(p, len, 1, stdout); 14 | } 15 | 16 | void printCStr(char *p) { 17 | printf("%s", p); 18 | } 19 | 20 | void printInt(int64_t nbr) { 21 | printf("%"PRId64, nbr); 22 | } 23 | 24 | void printUInt(uint64_t nbr) { 25 | printf("%"PRIu64, nbr); 26 | } 27 | 28 | void printFloat(double nbr) { 29 | printf("%g", nbr); 30 | } 31 | 32 | void printChar(uint64_t code) { 33 | char result[6]; 34 | char *p = &result[0]; 35 | 36 | if (code<0x80) 37 | *p++ = (unsigned char) code; 38 | else if (code<0x800) { 39 | *p++ = 0xC0 | (unsigned char)(code >> 6); 40 | *p++ = 0x80 | (code & 0x3f); 41 | } 42 | else if (code<0x10000) { 43 | *p++ = 0xE0 | (unsigned char)(code >> 12); 44 | *p++ = 0x80 | ((code >> 6) & 0x3F); 45 | *p++ = 0x80 | (code & 0x3f); 46 | } 47 | else if (code<0x110000) { 48 | *p++ = 0xF0 | (unsigned char)(code >> 18); 49 | *p++ = 0x80 | ((code >> 12) & 0x3F); 50 | *p++ = 0x80 | ((code >> 6) & 0x3F); 51 | *p++ = 0x80 | (code & 0x3f); 52 | } 53 | *p = '\0'; 54 | printf("%s", result); 55 | } -------------------------------------------------------------------------------- /src/c-compiler/ir/types/arrayref.h: -------------------------------------------------------------------------------- 1 | /** Handling for array reference (slice) type 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #ifndef arrayref_h 9 | #define arrayref_h 10 | 11 | // Serialize an array reference type 12 | void arrayRefPrint(RefNode *node); 13 | 14 | // Name resolution of an array reference node 15 | void arrayRefNameRes(NameResState *pstate, RefNode *node); 16 | 17 | // Semantically analyze an array reference node 18 | void arrayRefTypeCheck(TypeCheckState *pstate, RefNode *name); 19 | 20 | // Compare two reference signatures to see if they are equivalent 21 | int arrayRefIsSame(RefNode *node1, RefNode *node2); 22 | 23 | // Calculate hash for a structural reference type 24 | size_t arrayRefHash(RefNode *node); 25 | 26 | // Compare two reference signatures to see if they are equivalent at runtime 27 | int arrayRefIsRunSame(RefNode *node1, RefNode *node2); 28 | 29 | // Will from reference coerce to a to reference (we know they are not the same) 30 | TypeCompare arrayRefMatches(RefNode *to, RefNode *from, SubtypeConstraint constraint); 31 | 32 | // Will from reference coerce to a to arrayref (we know they are not the same) 33 | TypeCompare arrayRefMatchesRef(RefNode *to, RefNode *from, SubtypeConstraint constraint); 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /src/c-compiler/ir/exp/cast.h: -------------------------------------------------------------------------------- 1 | /** Handling for cast nodes 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #ifndef cast_h 9 | #define cast_h 10 | 11 | // Cast to another type 12 | typedef struct CastNode { 13 | IExpNodeHdr; 14 | INode *exp; 15 | INode *typ; 16 | } CastNode; 17 | 18 | #define FlagConvert 0x8000 // Cast should convert instead of re-cast (default) 19 | 20 | // Create node for recasting to a new type without conversion 21 | CastNode *newRecastNode(INode *exp, INode *type); 22 | 23 | // Create node for converting exp to a new type 24 | CastNode *newConvCastNode(INode *exp, INode *type); 25 | 26 | // Clone cast 27 | INode *cloneCastNode(CloneState *cstate, CastNode *node); 28 | 29 | // Create a new cast node 30 | CastNode *newIsNode(INode *exp, INode *type); 31 | 32 | void castPrint(CastNode *node); 33 | 34 | // Name resolution of cast node 35 | void castNameRes(NameResState *pstate, CastNode *node); 36 | 37 | // Type check cast node: 38 | // - reinterpret cast types must be same size 39 | // - Ensure type can be safely converted to target type 40 | void castTypeCheck(TypeCheckState *pstate, CastNode *node); 41 | 42 | // Analyze type comparison (is) node 43 | void castIsTypeCheck(TypeCheckState *pstate, CastNode *node); 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /src/c-compiler/ir/stmt/break.h: -------------------------------------------------------------------------------- 1 | /** Handling for break nodes 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #ifndef break_h 9 | #define break_h 10 | 11 | // Node info used by break, return, blockret, and continue statement nodes 12 | // Such statements are only (and must be) found at the end of a loop/regular block. 13 | // We share the same structure across all block-ending statements 14 | // so that we can substitute one for another (return -> break) and to find 15 | // field info in same place (even when not all are populated) 16 | typedef struct { 17 | INodeHdr; 18 | INode *exp; // value returned by break's/return's block (may be 'nil') 19 | INode *life; // lifetime for block scope to escape/re-start (null if none specified) 20 | BlockNode *block; // Block that this break/return applies to 21 | Nodes *dealias; // Nodes used to de-alias/unwind current block scope-allocated values 22 | } BreakRetNode; 23 | 24 | BreakRetNode *newBreakNode(); 25 | 26 | // Name resolution for break 27 | void breakNameRes(NameResState *pstate, BreakRetNode *node); 28 | 29 | // Clone break 30 | INode *cloneBreakNode(CloneState *cstate, BreakRetNode *node); 31 | 32 | void breakTypeCheck(TypeCheckState *pstate, BreakRetNode *node); 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /src/c-compiler/ir/exp/namedval.c: -------------------------------------------------------------------------------- 1 | /** Handling for named value nodes 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #include "../ir.h" 9 | 10 | // Create a new named value node 11 | NamedValNode *newNamedValNode(INode *name) { 12 | NamedValNode *node; 13 | newNode(node, NamedValNode, NamedValTag); 14 | node->vtype = unknownType; 15 | node->name = name; 16 | return node; 17 | } 18 | 19 | // Clone namedval 20 | INode *cloneNamedValNode(CloneState *cstate, NamedValNode *node) { 21 | NamedValNode *newnode; 22 | newnode = memAllocBlk(sizeof(NamedValNode)); 23 | memcpy(newnode, node, sizeof(NamedValNode)); 24 | newnode->name = cloneNode(cstate, node->name); 25 | newnode->val = cloneNode(cstate, node->val); 26 | return (INode *)newnode; 27 | } 28 | 29 | // Serialize named value node 30 | void namedValPrint(NamedValNode *node) { 31 | inodePrintNode(node->name); 32 | inodeFprint(": "); 33 | inodePrintNode(node->val); 34 | } 35 | 36 | // Name resolution of named value node 37 | void namedValNameRes(NameResState *pstate, NamedValNode *node) { 38 | inodeNameRes(pstate, &node->val); 39 | } 40 | 41 | // Type check named value node 42 | void namedValTypeCheck(TypeCheckState *pstate, NamedValNode *node) { 43 | if (iexpTypeCheckAny(pstate, &node->val) == 0) 44 | return; 45 | node->vtype = ((IExpNode*)node->val)->vtype; 46 | } 47 | -------------------------------------------------------------------------------- /src/c-compiler/ir/stmt/module.h: -------------------------------------------------------------------------------- 1 | /** Module and import structures and helper functions 2 | * 3 | * @file 4 | * 5 | * This source file is part of the Cone Programming Language C compiler 6 | * See Copyright Notice in conec.h 7 | */ 8 | 9 | #ifndef module_h 10 | #define module_h 11 | 12 | // Module is a global namespace owning (or folding in) many kinds of named nodes: 13 | // - Functions 14 | // - Global variables 15 | // - Type declarations (incl. permissions and allocators) 16 | // - Macro and template definitions 17 | // - Modules nested within this parent module (and names folded in from them) 18 | // 19 | // A module supports forward referencing of its names (except permissions and allocators). 20 | // It also supports name resolution of namespace qualified, public names. 21 | typedef struct ModuleNode { 22 | IExpNodeHdr; 23 | Name *namesym; 24 | Nodes *imports; // All import nodes 25 | Nodes *nodes; // All parsed nodes owned by the module 26 | Namespace namespace; // The module's named nodes, owned or "used" 27 | } ModuleNode; 28 | 29 | ModuleNode *newModuleNode(); 30 | void modPrint(ModuleNode *mod); 31 | void modAddNode(ModuleNode *mod, Name *name, INode *node); 32 | void modAddNamedNode(ModuleNode *mod, Name *name, INode *node); 33 | void modHook(ModuleNode *oldmod, ModuleNode *newmod); 34 | void modNameRes(NameResState *pstate, ModuleNode *mod); 35 | void modTypeCheck(TypeCheckState *pstate, ModuleNode *mod); 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /src/c-compiler/shared/options.h: -------------------------------------------------------------------------------- 1 | /** Option handling 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #ifndef options_h 9 | #define options_h 10 | 11 | #include 12 | 13 | // Option flag: Is extra info required, optional, or none needed? 14 | #define OPT_ARG_REQUIRED 1 15 | #define OPT_ARG_OPTIONAL 2 16 | #define OPT_ARG_NONE 4 17 | 18 | // Structure for a describing an option argument 19 | typedef struct opt_arg_t 20 | { 21 | char *long_opt; 22 | char short_opt; 23 | uint32_t flag; 24 | uint32_t id; 25 | } opt_arg_t; 26 | 27 | // Place this at end of option argument definition list 28 | #define OPT_ARGS_FINISH {NULL, 0, UINT32_MAX, UINT32_MAX} 29 | 30 | // State of the option decoder 31 | typedef struct opt_state_t 32 | { 33 | opt_arg_t* args; 34 | 35 | int *argc; 36 | char **argv; 37 | char *arg_val; 38 | 39 | // working state 40 | char *opt_start; 41 | char *opt_end; 42 | int match_type; 43 | int idx; 44 | int remove; 45 | } opt_state_t; 46 | 47 | // Initialize the option handling state 48 | void optInit(opt_arg_t *args, opt_state_t *s, int *argc, char **argv); 49 | 50 | // Retrieve the next valid and parsed option 51 | // If return is -1, we are done - no more to process 52 | // If return is -2, we found a badly formed option 53 | // Otherwise return is a match id, with arg_val containing the argument 54 | int optNext(opt_state_t *s); 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /src/c-compiler/ir/types/array.h: -------------------------------------------------------------------------------- 1 | /** Handling for array types 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #ifndef array_h 9 | #define array_h 10 | 11 | // Array node: Either an array type or an array literal 12 | typedef struct { 13 | ITypeNodeHdr; 14 | Nodes *dimens; // Dimensions of the array 15 | Nodes *elems; // Either a list of elements, or the element type 16 | } ArrayNode; 17 | 18 | // Create a new array node 19 | ArrayNode *newArrayNode(); 20 | 21 | // Clone array 22 | INode *cloneArrayNode(CloneState *cstate, ArrayNode *node); 23 | 24 | // Create a new array type of a specified size and element type 25 | ArrayNode *newArrayNodeTyped(INode *lexnode, size_t size, INode *elemtype); 26 | 27 | // Return the element type of the array type 28 | INode *arrayElemType(INode *array); 29 | 30 | // Return the size of the first dimension (assuming 1-dimensional array) 31 | uint64_t arrayDim1(INode *array); 32 | 33 | void arrayPrint(ArrayNode *node); 34 | 35 | // Name resolution of an array type 36 | void arrayNameRes(NameResState *pstate, ArrayNode *node); 37 | 38 | // Type check an array type 39 | void arrayTypeCheck(TypeCheckState *pstate, ArrayNode *name); 40 | 41 | int arrayEqual(ArrayNode *node1, ArrayNode *node2); 42 | 43 | // Is from-type a subtype of to-struct (we know they are not the same) 44 | TypeCompare arrayMatches(ArrayNode *to, ArrayNode *from, SubtypeConstraint constraint); 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /src/c-compiler/ir/namespace.h: -------------------------------------------------------------------------------- 1 | /** Hashed named nodes 2 | * 3 | * The module node is a namespace, as it contains an unordered collection 4 | * of potentially many named nodes: functions, variables, types, sub-modules, etc. 5 | * 6 | * These functions support managing a module's named nodes as a hash table 7 | * for high-performing lookup access to a specific name. 8 | * 9 | * @file 10 | * 11 | * This source file is part of the Cone Programming Language C compiler 12 | * See Copyright Notice in conec.h 13 | */ 14 | 15 | #ifndef namespace_h 16 | #define namespace_h 17 | 18 | // A namespace entry 19 | typedef struct NameNode { 20 | Name *name; 21 | INode *node; 22 | } NameNode; 23 | 24 | // Namespace metadata 25 | typedef struct Namespace { 26 | size_t avail; 27 | size_t used; 28 | NameNode *namenodes; 29 | } Namespace; 30 | 31 | // Initialize a module's namespace with a specific number of slots 32 | void namespaceInit(Namespace *ns, size_t avail); 33 | 34 | // Return the module's node for a name (or NULL if none) 35 | INode *namespaceFind(Namespace *ns, Name *name); 36 | 37 | // Add or change the node a modue's name maps to 38 | void namespaceSet(Namespace *ns, Name *name, INode *node); 39 | 40 | // Add the node a name maps to if no conflict and return NULL. 41 | // Otherwise, return the node already there 42 | INode *namespaceAdd(Namespace *ns, Name *name, INode *node); 43 | 44 | // Iterate through a module's namespace 45 | #define namespaceFor(ns) for (size_t __i = 0; __i < (ns)->avail; ++__i) 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /src/c-compiler/ir/stmt/import.c: -------------------------------------------------------------------------------- 1 | /** import node helper routines 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #include "../ir.h" 9 | 10 | #include 11 | #include 12 | 13 | // Create a new Import node 14 | ImportNode *newImportNode() { 15 | ImportNode *node; 16 | newNode(node, ImportNode, ImportTag); 17 | node->module = NULL; 18 | node->foldall = 0; 19 | return node; 20 | } 21 | 22 | // Serialize a import node 23 | void importPrint(ImportNode *node) { 24 | inodeFprint("import %s", node->module? &node->module->namesym->namestr : "stdio"); 25 | if (node->foldall) 26 | inodeFprint("::*"); 27 | } 28 | 29 | // Name resolution of the import node 30 | void importNameRes(NameResState *pstate, ImportNode *node) { 31 | if (!node->foldall || !node->module) 32 | return; 33 | 34 | ModuleNode *sourcemod = node->module; 35 | ModuleNode *targetmod = pstate->mod; 36 | 37 | // Process all nodes 38 | INode **nodesp; 39 | uint32_t cnt; 40 | for (nodesFor(sourcemod->nodes, cnt, nodesp)) { 41 | if (!isNamedNode(*nodesp)) 42 | continue; 43 | modAddNamedNode(targetmod, inodeGetName(*nodesp), *nodesp); 44 | } 45 | } 46 | 47 | // Type check the import node 48 | void importTypeCheck(TypeCheckState *pstate, ImportNode *node) { 49 | // Type check the module we are importing 50 | inodeTypeCheckAny(pstate, (INode**)&node->module); 51 | } 52 | -------------------------------------------------------------------------------- /src/c-compiler/ir/types/lifetime.h: -------------------------------------------------------------------------------- 1 | /** Lifetime Annotations (Variables) 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #ifndef lifetime_h 9 | #define lifetime_h 10 | 11 | typedef struct NameUseNode NameUseNode; 12 | 13 | // A lifetime is effectively two numbers from 0-255 that describe a partial order. 14 | // - Group. Two lifetimes with different groups (>1) cannot be subtypes of each other 15 | // A new group is assigned for each implicit/explicit lifetime annotation on a generic 16 | // 'static and local scopes have a group of 0. 17 | // - Scope. A higher number is a subtype of a lower number. 0='static, 16+=local scopes 18 | typedef uint16_t Lifetime; 19 | 20 | // Lifetime type info 21 | typedef struct LifetimeNode { 22 | ITypeNodeHdr; 23 | Name *namesym; 24 | Lifetime life; 25 | } LifetimeNode; 26 | 27 | // Create a new lifetime declaration node 28 | LifetimeNode *newLifetimeDclNode(Name *namesym, Lifetime life); 29 | 30 | // Create a copy of lifetime dcl 31 | INode *cloneLifetimeDclNode(CloneState *cstate, LifetimeNode *node); 32 | 33 | // Create a new lifetime use node 34 | INode *newLifetimeUseNode(LifetimeNode *lifedcl); 35 | 36 | // Serialize a lifetime node 37 | void lifePrint(LifetimeNode *node); 38 | 39 | // Are the lifetimes the same? 40 | int lifeIsSame(INode *node1, INode *node2); 41 | 42 | // Will 'from' lifetime coerce to the target? 43 | int lifeMatches(INode *to, INode *from); 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /src/c-compiler/ir/nodelist.h: -------------------------------------------------------------------------------- 1 | /** Shared logic for namespace-based types 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #ifndef nodelist_h 9 | #define nodelist_h 10 | 11 | // Variable-sized structure holding an ordered list of Nodes 12 | typedef struct NodeList { 13 | uint32_t used; 14 | uint32_t avail; 15 | INode **nodes; 16 | } NodeList; 17 | 18 | // Initialize methnodes metadata in a method type node 19 | void nodelistInit(NodeList *mnodes, uint32_t size); 20 | 21 | // Iterate through the set of NodeList 22 | #define nodelistFor(mnodes, cnt, nodesp) nodesp = (mnodes)->nodes, cnt = (mnodes)->used; cnt; cnt--, nodesp++ 23 | 24 | // Point to the indexth node in an NodeList 25 | #define nodelistGet(mnodes, index) (mnodes)->nodes[index] 26 | 27 | // Point to the last node in an NodeList 28 | #define nodelistLast(mnodes) nodelistGet(mnodes, mnodes->used-1) 29 | 30 | // Add an INode to the end of a NodeList, growing it if full (changing its memory location) 31 | void nodelistAdd(NodeList *mnodes, INode *node); 32 | 33 | // Insert a node into a nodelist at pos 34 | void nodelistInsert(NodeList *mnodes, uint32_t pos, INode *node); 35 | 36 | // Insert some list into another list, beginning at index 37 | void nodelistInsertList(NodeList *mnodes, NodeList *fromnodes, uint32_t index); 38 | 39 | // Open up space for amt new nodes beginning at pos. 40 | // If amt is negative, delete that number of nodes 41 | void nodelistMakeSpace(NodeList *nodes, size_t pos, int32_t amt); 42 | 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /src/c-compiler/ir/nodes.h: -------------------------------------------------------------------------------- 1 | /** Node List 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #ifndef nodes_h 9 | #define nodes_h 10 | 11 | typedef struct INode INode; 12 | typedef struct OwnerNode OwnerNode; 13 | typedef struct Name Name; 14 | 15 | #include 16 | 17 | // *** Nodes: Dynamically-sized array of Nodes *** 18 | 19 | // Header for a variable-sized structure holding a list of Nodes 20 | // The nodes immediately follow the header 21 | typedef struct Nodes { 22 | uint32_t used; 23 | uint32_t avail; 24 | } Nodes; 25 | 26 | // Helper Functions 27 | Nodes *newNodes(int size); 28 | 29 | // Make a deep clone of a Nodes structure 30 | typedef struct CloneState CloneState; 31 | Nodes *cloneNodes(CloneState *cstate, Nodes *oldnodes); 32 | 33 | void nodesAdd(Nodes **nodesp, INode *node); 34 | void nodesInsert(Nodes **nodesp, INode *node, size_t index); 35 | // Move an element at index 'to' to index 'from', shifting nodes in between 36 | void nodesMove(Nodes *nodes, size_t to, size_t from); 37 | 38 | // Open up space for amt new nodes beginning at pos. 39 | // If amt is negative, delete that number of nodes 40 | void nodesMakeSpace(Nodes **nodesp, size_t pos, int32_t amt); 41 | 42 | #define nodesNodes(nodes) ((INode**)((nodes)+1)) 43 | #define nodesFor(nodes, cnt, nodesp) nodesp = (INode**)((nodes)+1), cnt = (nodes)->used; cnt; cnt--, nodesp++ 44 | #define nodesGet(nodes, index) ((INode**)((nodes)+1))[index] 45 | #define nodesLast(nodes) nodesGet(nodes, nodes->used-1) 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /src/c-compiler/ir/exp/deref.c: -------------------------------------------------------------------------------- 1 | /** Handling for deref nodes 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #include "../ir.h" 9 | 10 | // Inject automatic deref node, if node's type is a ref or ptr. Return 1 if dereffed. 11 | int derefInject(INode **node) { 12 | INode *nodetype = iexpGetTypeDcl(*node); 13 | if (nodetype->tag != RefTag && nodetype->tag != PtrTag) 14 | return 0; 15 | StarNode *deref = newStarNode(DerefTag); 16 | deref->vtexp = *node; 17 | if (nodetype->tag == PtrTag) 18 | deref->vtype = ((StarNode*)((IExpNode *)*node)->vtype)->vtexp; 19 | else 20 | deref->vtype = ((RefNode*)((IExpNode *)*node)->vtype)->vtexp; 21 | *node = (INode*)deref; 22 | return 1; 23 | } 24 | 25 | // Serialize deref 26 | void derefPrint(StarNode *node) { 27 | inodeFprint("*"); 28 | inodePrintNode(node->vtexp); 29 | } 30 | 31 | // Type check deref node 32 | void derefTypeCheck(TypeCheckState *pstate, StarNode *node) { 33 | if (iexpTypeCheckAny(pstate, &node->vtexp) == 0) 34 | return; 35 | 36 | INode *ptype = ((IExpNode *)node->vtexp)->vtype; 37 | if (ptype->tag == RefTag) 38 | node->vtype = ((RefNode*)ptype)->vtexp; 39 | else if (ptype->tag == PtrTag) 40 | node->vtype = ((StarNode*)ptype)->vtexp; 41 | else 42 | errorMsgNode((INode*)node, ErrorNotPtr, "May only de-reference a simple reference or pointer."); 43 | } 44 | 45 | // Perform data flow analysis on deref node 46 | void derefFlow(FlowState *fstate, StarNode **node) { 47 | flowLoadValue(fstate, &(*node)->vtexp); 48 | } 49 | -------------------------------------------------------------------------------- /src/c-compiler/ir/stmt/intrinsic.h: -------------------------------------------------------------------------------- 1 | /** Handling for intrinsic nodes 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #ifndef intrinsic_h 9 | #define intrinsic_h 10 | 11 | // The various intrinsic functions supported by IntrinsicNode 12 | enum IntrinsicFn { 13 | // Arithmetic 14 | NegIntrinsic, 15 | IsTrueIntrinsic, 16 | AddIntrinsic, 17 | SubIntrinsic, 18 | MulIntrinsic, 19 | DivIntrinsic, 20 | SDivIntrinsic, 21 | RemIntrinsic, 22 | SRemIntrinsic, 23 | IncrIntrinsic, 24 | DecrIntrinsic, 25 | IncrPostIntrinsic, 26 | DecrPostIntrinsic, 27 | DiffIntrinsic, // subtract two pointers 28 | AddEqIntrinsic, 29 | SubEqIntrinsic, 30 | 31 | // Comparison 32 | EqIntrinsic, 33 | NeIntrinsic, 34 | LtIntrinsic, 35 | LeIntrinsic, 36 | GtIntrinsic, 37 | GeIntrinsic, 38 | SLtIntrinsic, 39 | SLeIntrinsic, 40 | SGtIntrinsic, 41 | SGeIntrinsic, 42 | 43 | // Bitwise 44 | NotIntrinsic, 45 | AndIntrinsic, 46 | OrIntrinsic, 47 | XorIntrinsic, 48 | ShlIntrinsic, 49 | ShrIntrinsic, 50 | SShrIntrinsic, 51 | 52 | // Reference methods 53 | CountIntrinsic, 54 | 55 | // Intrinsic functions 56 | SqrtIntrinsic, 57 | SinIntrinsic, 58 | CosIntrinsic 59 | }; 60 | 61 | // An internal operation (e.g., add). 62 | // Used as an alternative to FnDcl->value = Block within a function declaration. 63 | typedef struct IntrinsicNode { 64 | INodeHdr; 65 | int16_t intrinsicFn; 66 | } IntrinsicNode; 67 | 68 | IntrinsicNode *newIntrinsicNode(int16_t intrinsicFn); 69 | 70 | #endif 71 | -------------------------------------------------------------------------------- /src/c-compiler/ir/clone.h: -------------------------------------------------------------------------------- 1 | /** The Cloning pass that performs a deep copy of all nodes under the target node 2 | 3 | * - Clone parameters (including Self) substitute their instantiated values 4 | * - Variables are hygienic and generally not shared between contexts 5 | * 6 | * @file 7 | * 8 | * This source file is part of the Cone Programming Language C compiler 9 | * See Copyright Notice in conec.h 10 | */ 11 | 12 | #ifndef clone_h 13 | #define clone_h 14 | 15 | // Context used across the cloning pass 16 | typedef struct CloneState { 17 | INode *instnode; // The node provoking instantiation (for error messages) 18 | INode *selftype; // Self type (might be NULL) 19 | uint16_t scope; // Current block level 20 | } CloneState; 21 | 22 | // Data structures used for fixing dcl pointers 23 | typedef struct CloneDclMap { 24 | INode *original; 25 | INode *clone; 26 | } CloneDclMap; 27 | 28 | // Perform a deep clone of specified node 29 | INode *cloneNode(CloneState *cstate, INode *nodep); 30 | 31 | // Set the state needed for deep cloning some node 32 | void clonePushState(CloneState *cstate, INode *instnode, INode *selftype, uint32_t scope, Nodes *parms, Nodes *args); 33 | 34 | // Release the acquired state 35 | void clonePopState(); 36 | 37 | // Preserve high-water position in the dcl stack 38 | uint32_t cloneDclPush(); 39 | 40 | // Restore high-water position in the dcl stack 41 | void cloneDclPop(uint32_t pos); 42 | 43 | // Remember a mapping of a declaration node between the original and a copy 44 | void cloneDclSetMap(INode *orig, INode *clone); 45 | 46 | // Return the new pointer to the dcl node, given the original pointer 47 | INode *cloneDclFix(INode *orig); 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /src/c-compiler/ir/stmt/fndcl.h: -------------------------------------------------------------------------------- 1 | /** Handling for function/method declaration nodes 2 | * 3 | * This source file is part of the Cone Programming Language C compiler 4 | * See Copyright Notice in conec.h 5 | */ 6 | 7 | #ifndef fndcl_h 8 | #define fndcl_h 9 | 10 | // Function/method declaration node 11 | typedef struct FnDclNode { 12 | IExpNodeHdr; // 'vtype': type of this name's value 13 | Name *namesym; 14 | INode *value; // Block or intrinsic code nodes (NULL if no code) 15 | LLVMValueRef llvmvar; // LLVM's handle for a declared variable (for generation) 16 | char *genname; // Name of the function as known to the linker 17 | struct FnDclNode *nextnode; // Link to next overloaded method with the same name (or NULL) 18 | GenericInfo *genericinfo; // Link to generic parms, etc (or NULL if not generic) 19 | uint16_t vtblidx; // Method ptr's index in the type's vtable 20 | } FnDclNode; 21 | 22 | // Create a new function declaraction node 23 | FnDclNode *newFnDclNode(Name *namesym, uint16_t tag, INode *sig, INode *val); 24 | 25 | // Return a clone of a function/method declaration 26 | INode *cloneFnDclNode(CloneState *cstate, FnDclNode *oldfn); 27 | 28 | void fnDclPrint(FnDclNode *fn); 29 | 30 | /// Resolve all names in a function 31 | void fnDclNameRes(NameResState *pstate, FnDclNode *name); 32 | 33 | // Type checking a function's logic, does more than you might think: 34 | // - Turn implicit returns into explicit returns 35 | // - Perform type checking for all statements 36 | // - Perform data flow analysis on variables and references 37 | void fnDclTypeCheck(TypeCheckState *pstate, FnDclNode *fnnode); 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /src/c-compiler/corelib/corelib.h: -------------------------------------------------------------------------------- 1 | /** Standard library initialiation 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #ifndef stdlib_h 9 | #define stdlib_h 10 | 11 | // Unique (unclonable) nodes representing the absence of value or type 12 | extern INode *unknownType; // Unknown/unspecified type 13 | extern INode *noCareType; // When the receiver does not care what type is returned 14 | extern INode *elseCond; // node representing the 'else' condition for an 'if' node 15 | extern INode *borrowRef; // When a reference's region is unspecified, as it is borrowed 16 | 17 | // Built-in permission types - for implicit (non-declared but known) permissions 18 | extern PermNode *uniPerm; 19 | extern PermNode *mutPerm; 20 | extern PermNode *immPerm; 21 | extern PermNode *roPerm; 22 | extern PermNode *mut1Perm; 23 | extern PermNode *opaqPerm; 24 | 25 | // Built-in lifetimes 26 | extern LifetimeNode *staticLifetimeNode; 27 | 28 | // Primitive numeric types - for implicit (nondeclared but known) types 29 | extern NbrNode *boolType; // i1 30 | extern NbrNode *i8Type; 31 | extern NbrNode *i16Type; 32 | extern NbrNode *i32Type; 33 | extern NbrNode *i64Type; 34 | extern NbrNode *isizeType; 35 | extern NbrNode *u8Type; 36 | extern NbrNode *u16Type; 37 | extern NbrNode *u32Type; 38 | extern NbrNode *u64Type; 39 | extern NbrNode *usizeType; 40 | extern NbrNode *f32Type; 41 | extern NbrNode *f64Type; 42 | 43 | extern INsTypeNode *ptrType; 44 | extern INsTypeNode *refType; 45 | extern INsTypeNode *arrayRefType; 46 | 47 | extern char *corelibSource; 48 | 49 | void stdlibInit(int ptrsize); 50 | void keywordInit(); 51 | void stdNbrInit(int ptrsize); 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /src/c-compiler/conec.h: -------------------------------------------------------------------------------- 1 | /** Include file for Cone compiler 2 | * @file 3 | * 4 | * This source file is part of Cone Programming Language C compiler. 5 | * Copyright (C) 2017-2021 Jonathan Goodwin 6 | * 7 | * Permission is hereby granted, free of charge, to any 8 | * person obtaining a copy of this software and associated 9 | * documentation files (the "Software"), to deal in the 10 | * Software without restriction, including without 11 | * limitation the rights to use, copy, modify, merge, 12 | * publish, distribute, sublicense, and/or sell copies of 13 | * the Software, and to permit persons to whom the Software 14 | * is furnished to do so, subject to the following 15 | * conditions: 16 | * 17 | * The above copyright notice and this permission notice 18 | * shall be included in all copies or substantial portions 19 | * of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 22 | * ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 23 | * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 24 | * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 25 | * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 26 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 27 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 28 | * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 29 | * DEALINGS IN THE SOFTWARE. 30 | */ 31 | 32 | #ifndef conec_h 33 | #define conec_h 34 | 35 | #define CONE_VERSION_MAJOR "0" 36 | #define CONE_VERSION_MINOR "1" 37 | #define CONE_VERSION_NUM 1 38 | #define CONE_VERSION_RELEASE "0" 39 | 40 | #define CONE_VERSION "Cone Compiler " CONE_VERSION_MAJOR "." CONE_VERSION_MINOR 41 | #define CONE_RELEASE CONE_VERSION "." CONE_VERSION_RELEASE 42 | #define CONE_COPYRIGHT CONE_RELEASE " Copyright (C) 2017-2021 Jonathan Goodwin" 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /src/c-compiler/ir/types/pointer.c: -------------------------------------------------------------------------------- 1 | /** Handling for pointers 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #include "../ir.h" 9 | #include 10 | 11 | // Create a new "star" node (ptr type or deref exp) whose vtexp will be filled in later 12 | StarNode *newStarNode(uint16_t tag) { 13 | StarNode *node; 14 | newNode(node, StarNode, tag); 15 | node->vtype = unknownType; 16 | return node; 17 | } 18 | 19 | // Clone ptr or deref node 20 | INode *cloneStarNode(CloneState *cstate, StarNode *node) { 21 | StarNode *newnode = memAllocBlk(sizeof(StarNode)); 22 | memcpy(newnode, node, sizeof(StarNode)); 23 | newnode->vtexp = cloneNode(cstate, node->vtexp); 24 | return (INode *)newnode; 25 | } 26 | 27 | // Serialize a pointer type 28 | void ptrPrint(StarNode *node) { 29 | inodeFprint("*"); 30 | inodePrintNode(node->vtexp); 31 | } 32 | 33 | // Name resolution of a pointer type 34 | void ptrNameRes(NameResState *pstate, StarNode *node) { 35 | inodeNameRes(pstate, &node->vtexp); 36 | node->tag = isTypeNode(node->vtexp) ? PtrTag : DerefTag; 37 | } 38 | 39 | // Type check a pointer type 40 | void ptrTypeCheck(TypeCheckState *pstate, StarNode *node) { 41 | if (itypeTypeCheck(pstate, &node->vtexp) == 0) 42 | return; 43 | } 44 | 45 | // Compare two pointer signatures to see if they are equivalent 46 | int ptrEqual(StarNode *node1, StarNode *node2) { 47 | return itypeIsSame(node1->vtexp, node2->vtexp); 48 | } 49 | 50 | // Will from pointer coerce to a to pointer 51 | TypeCompare ptrMatches(StarNode *to, StarNode *from, SubtypeConstraint constraint) { 52 | // Since pointers support both read and write permissions, value type invariance is expected 53 | return itypeIsSame(to->vtexp, from->vtexp)? EqMatch : NoMatch; 54 | } 55 | -------------------------------------------------------------------------------- /src/c-compiler/ir/stmt/vardcl.h: -------------------------------------------------------------------------------- 1 | /** Handling for variable declaration nodes 2 | * 3 | * This source file is part of the Cone Programming Language C compiler 4 | * See Copyright Notice in conec.h 5 | */ 6 | 7 | #ifndef vardcl_h 8 | #define vardcl_h 9 | 10 | // Variable declaration node (global, local, parm) 11 | typedef struct VarDclNode { 12 | IExpNodeHdr; // 'vtype': type of this name's value 13 | Name *namesym; 14 | INode *value; // Starting value/declaration (NULL if not initialized) 15 | LLVMValueRef llvmvar; // LLVM's handle for a declared variable (for generation) 16 | char *genname; // Name of variable as known to the linker 17 | INode *perm; // Permission type (often mut or imm) 18 | uint16_t scope; // 0=global 19 | uint16_t index; // index within this scope (e.g., parameter number) 20 | uint16_t flowflags; // Data flow pass permanent flags 21 | uint16_t flowtempflags; // Data flow pass temporary flags 22 | } VarDclNode; 23 | 24 | enum VarFlowTemp { 25 | VarInitialized = 0x0001, // Variable has been initialized 26 | VarMoved = 0x0002 // Variable has been moved 27 | }; 28 | 29 | VarDclNode *newVarDclNode(Name *namesym, uint16_t tag, INode *perm); 30 | VarDclNode *newVarDclFull(Name *namesym, uint16_t tag, INode *sig, INode *perm, INode *val); 31 | 32 | // Create a new variable dcl node that is a copy of an existing one 33 | INode *cloneVarDclNode(CloneState *cstate, VarDclNode *node); 34 | 35 | void varDclPrint(VarDclNode *fn); 36 | 37 | // Name resolution of vardcl 38 | void varDclNameRes(NameResState *pstate, VarDclNode *node); 39 | 40 | // Type check vardcl 41 | void varDclTypeCheck(TypeCheckState *pstate, VarDclNode *node); 42 | 43 | // Perform data flow analysis 44 | void varDclFlow(FlowState *fstate, VarDclNode **vardclnode); 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Cone 2 | 3 | Thank you for your interest in contributing to Cone! There are many ways to contribute and we appreciate all of them. 4 | 5 | Here is an incomplete list of possibilities: 6 | 7 | - **Language & Compiler**: Find bugs, fix bugs, suggest designs, or implement designed features. 8 | - **Tools**: Editor/IDE plug-ins, installation scripts, Congo build tool, package management, playground, linter, etc. 9 | - **Package Libraries**: Types (e.g., math libraries, collections, ...), memory regions, concurrency, I/O, etc. 10 | - **Documentation**: Cone home page, reference documentation, etc. (including art design on layout, logos, etc.) 11 | 12 | We want mutually-beneficial contributions: 13 | those that match your enthusiasm and skills to what will best fulfill Cone's vision for the future. 14 | The only way to sort that out is by building a relationship with you, where we get to know each other 15 | and decide together a mutually-enjoyable contribution plan, step-by-step. 16 | 17 | The best way to get started is: 18 | 19 | - Learn more about Cone from the https://cone.jondgoodwin.com website. 20 | Here you will find: 21 | 22 | - Summary pages describing its goals and key features. 23 | - A detailed reference guide to the language. 24 | - A playground you can use to learn Cone by doing, without having to install the compiler on your machine. 25 | - A blog whose posts provide helpful context on the rationale behind many of Cone's more intriguing features, 26 | as well as architectural design decisions for the compiler. 27 | 28 | - Join the Cone community on Discord (see the link on the Cone homepage). 29 | Here you can ask questions, suggest improvements, build relationships, and explore ideas on where to contribute. 30 | 31 | If you find bugs or have suggestions for improvement, 32 | we encourage you to create new Github issues followed later by Pull Requests (PRs). 33 | The Discord server is the best place for questions, discussions, and building relationships and synergy. -------------------------------------------------------------------------------- /src/c-compiler/ir/stmt/continue.c: -------------------------------------------------------------------------------- 1 | /** Handling for continue nodes 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #include "../ir.h" 9 | 10 | // Create a new continue node 11 | BreakRetNode *newContinueNode() { 12 | BreakRetNode *node; 13 | newNode(node, BreakRetNode, ContinueTag); 14 | node->life = NULL; 15 | node->dealias = NULL; 16 | return node; 17 | } 18 | 19 | // Clone continue 20 | INode *cloneContinueNode(CloneState *cstate, BreakRetNode *node) { 21 | BreakRetNode *newnode; 22 | newnode = memAllocBlk(sizeof(BreakRetNode)); 23 | memcpy(newnode, node, sizeof(BreakRetNode)); 24 | newnode->block = (BlockNode *)cloneDclFix((INode*)node->block); 25 | return (INode *)newnode; 26 | } 27 | 28 | // Name resolution for continue 29 | // - Resolve any lifetime name 30 | void continueNameRes(NameResState *nstate, BreakRetNode *continuenode) { 31 | // Resolve continue to block it applies to 32 | if (continuenode->life) { 33 | // If a lifetime was specified, resolve to lifetime-named block 34 | inodeNameRes(nstate, &continuenode->life); 35 | BlockNode *block = (BlockNode*)((NameUseNode*)(continuenode->life))->dclnode; 36 | if (block && block->tag == BlockTag && (block->flags & FlagLoop)) { 37 | continuenode->block = block; 38 | } 39 | else { 40 | errorMsgNode((INode*)continuenode, ErrorNoLoop, "break's lifetime not found on a lifetime-named looping block"); 41 | } 42 | } 43 | else { 44 | // If no lifetime specified, resolve to inner-most loop block 45 | if (nstate->loopblock) 46 | continuenode->block = nstate->loopblock; 47 | else 48 | errorMsgNode((INode*)continuenode, ErrorNoLoop, "continue may only be used within a while/each/loop block"); 49 | } 50 | } 51 | 52 | // Type check the continue node 53 | void continueTypeCheck(TypeCheckState *pstate, BreakRetNode *node) { 54 | } 55 | -------------------------------------------------------------------------------- /src/c-compiler/ir/exp/block.h: -------------------------------------------------------------------------------- 1 | /** Handling for block nodes 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #ifndef block_h 9 | #define block_h 10 | 11 | // Block is a ordered sequence of executable statements within a function. 12 | // There are two varieties: 13 | // - regular block that performs its statements once and then moves on 14 | // - loop block that automatically repeats its statements forever 15 | // Every block must end with one of these statements: return, break, continue or "block return" 16 | // 17 | // A block establishes a local execution context, a namespace that owns local variables. 18 | // Local variables are uniquely named and cannot be forward referenced. 19 | // 20 | // A block can have a named lifetime. When it does, one can break and continue to it. 21 | typedef struct BlockNode { 22 | IExpNodeHdr; 23 | Nodes *stmts; 24 | Name *lifesym; // nullable 25 | Nodes *breaks; 26 | } BlockNode; 27 | 28 | BlockNode *newBlockNode(); 29 | BlockNode *newLoopBlockNode(); 30 | 31 | // Clone block 32 | INode *cloneBlockNode(CloneState *cstate, BlockNode *node); 33 | 34 | void blockPrint(BlockNode *blk); 35 | 36 | // Handle name resolution and control structure compliance for a block 37 | // - push and pop a namespace context for hooking local vars in global name table 38 | // - Ensure return/continue/break only appear as last statement in block 39 | void blockNameRes(NameResState *pstate, BlockNode *blk); 40 | 41 | // Handle type-checking for a block's statements. 42 | // Note: When coerced by iexpCoerces, vtype of the block will be specified 43 | void blockTypeCheck(TypeCheckState *pstate, BlockNode *blkvz, INode *expectType); 44 | 45 | // Ensure this particular block does not end with break/continue 46 | // Used by regular and loop blocks, but not by 'if' based blocks 47 | void blockNoBreak(BlockNode *blk); 48 | 49 | // Perform data flow analysis 50 | void blockFlow(FlowState *fstate, BlockNode **blknode); 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /src/c-compiler/ir/stmt/program.c: -------------------------------------------------------------------------------- 1 | /** Program node helper routines 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #include "../ir.h" 9 | 10 | #include 11 | #include 12 | 13 | // Create a new Program node 14 | ProgramNode *newProgramNode() { 15 | ProgramNode *pgm; 16 | newNode(pgm, ProgramNode, ProgramTag); 17 | pgm->modules = newNodes(4); 18 | return pgm; 19 | } 20 | 21 | // Add a new module to the program 22 | ModuleNode *pgmAddMod(ProgramNode *pgm, int16_t flags) { 23 | ModuleNode *mod = newModuleNode(); 24 | mod->flags |= flags; 25 | nodesAdd(&pgm->modules, (INode*)mod); 26 | return mod; 27 | } 28 | 29 | // Find an already parsed module, or return NULL if not found 30 | ModuleNode *pgmFindMod(ProgramNode *pgm, Name *modname) { 31 | INode **nodesp; 32 | uint32_t cnt; 33 | for (nodesFor(pgm->modules, cnt, nodesp)) { 34 | ModuleNode *mod = (ModuleNode *)*nodesp; 35 | if (mod->namesym == modname) 36 | return mod; 37 | } 38 | return NULL; 39 | } 40 | 41 | // Serialize a program node 42 | void pgmPrint(ProgramNode *pgm) { 43 | inodeFprint("program:\n"); 44 | inodePrintIncr(); 45 | INode **nodesp; 46 | uint32_t cnt; 47 | for (nodesFor(pgm->modules, cnt, nodesp)) { 48 | inodePrintIndent(); 49 | inodePrintNode(*nodesp); 50 | inodePrintNL(); 51 | } 52 | inodePrintDecr(); 53 | } 54 | 55 | // Name resolution of the program node 56 | void pgmNameRes(NameResState *pstate, ProgramNode *pgm) { 57 | INode **nodesp; 58 | uint32_t cnt; 59 | for (nodesFor(pgm->modules, cnt, nodesp)) { 60 | inodeNameRes(pstate, nodesp); 61 | } 62 | } 63 | 64 | // Type check the program node 65 | void pgmTypeCheck(TypeCheckState *pstate, ProgramNode *pgm) { 66 | INode **nodesp; 67 | uint32_t cnt; 68 | for (nodesFor(pgm->modules, cnt, nodesp)) { 69 | inodeTypeCheckAny(pstate, nodesp); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/c-compiler/ir/typetbl.h: -------------------------------------------------------------------------------- 1 | /** Hashed table for normalizing equivalent structural types to single definition 2 | * For use by LLVM generation and for preserving useful metadata. 3 | * 4 | * Nominal types are uniquely defined, with a name being used to refer to the type's singular definition 5 | * Structural types (references/pointers, arrays, tuples) redefine the type each time, 6 | * which forces type matching to compare all elements for equivalence 7 | * This global Structural Type table allows us to collapse all equivalent definitions 8 | * for a structural type into a single definitional object. 9 | * - This speeds up creation and reuse of the LLVM type 10 | * - This single definition can hold constructed metadata for the type, particularly the 11 | * field and method table for region-managed references (alloc, free, deref, etc.) 12 | * 13 | * @file 14 | * 15 | * This source file is part of the Cone Programming Language C compiler 16 | * See Copyright Notice in conec.h 17 | */ 18 | 19 | #ifndef typetbl_h 20 | #define typetbl_h 21 | 22 | #include "ir.h" 23 | 24 | #include 25 | 26 | typedef struct { 27 | INode *type; // Type node to compare against 28 | size_t hash; // Type's computed hash 29 | void *normal; // Normalized type metadata 30 | } TypeTblEntry; 31 | 32 | // Global Type Table configuration variables 33 | extern size_t gTypeTblInitSize; // Initial maximum number of unique types (must be power of 2) 34 | extern unsigned int gTypeTblUtil; // % utilization that triggers doubling of table 35 | 36 | // Allocate and initialize the global type table 37 | void typetblInit(); 38 | 39 | // Get pointer to the type's normal metadata for the structural type in the global type table 40 | // For an unknown type, it allocates memory for the metadata and adds it to type table. 41 | void *typetblFind(INode *type, void *(*allocfn)()); 42 | 43 | // Return how many bytes have been allocated for global type table but not yet used 44 | size_t typetblUnused(); 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /src/c-compiler/ir/exp/literal.h: -------------------------------------------------------------------------------- 1 | /** Handling for literals 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #ifndef literal_h 9 | #define literal_h 10 | 11 | // Nil literal node: represents the absence of a value. Always has type "void" 12 | typedef struct { 13 | IExpNodeHdr; 14 | } NilLitNode; 15 | 16 | // Unsigned integer literal 17 | typedef struct { 18 | IExpNodeHdr; 19 | uint64_t uintlit; 20 | } ULitNode; 21 | 22 | // Float literal 23 | typedef struct { 24 | IExpNodeHdr; 25 | double floatlit; 26 | } FLitNode; 27 | 28 | // String literal 29 | typedef struct { 30 | IExpNodeHdr; 31 | char *strlit; 32 | uint32_t strlen; 33 | } SLitNode; 34 | 35 | NilLitNode *newNilLitNode(); 36 | INode *cloneNilLitNode(CloneState *cstate, NilLitNode *node); 37 | void nilLitPrint(NilLitNode *node); 38 | 39 | // Create a new fake unsigned literal node 40 | ULitNode *newFakeULitNode(uint64_t nbr, INode *type); 41 | 42 | ULitNode *newULitNode(uint64_t nbr, INode *type); 43 | 44 | // Create a new unsigned literal node (after name resolution) 45 | ULitNode *newULitNodeTC(uint64_t nbr, INode *type); 46 | 47 | // Clone literal 48 | INode *cloneULitNode(CloneState *cstate, ULitNode *lit); 49 | 50 | void ulitPrint(ULitNode *node); 51 | 52 | FLitNode *newFLitNode(double nbr, INode *type); 53 | void flitPrint(FLitNode *node); 54 | 55 | // Clone literal 56 | INode *cloneFLitNode(CloneState *cstate, FLitNode *lit); 57 | 58 | // Name resolution of lit node 59 | void litNameRes(NameResState* pstate, IExpNode *node); 60 | 61 | // Type check lit node 62 | void litTypeCheck(TypeCheckState* pstate, IExpNode *node, INode *expectType); 63 | 64 | SLitNode *newSLitNode(char *str, uint32_t strlen); 65 | 66 | // Clone literal 67 | INode *cloneSLitNode(SLitNode *lit); 68 | 69 | void slitPrint(SLitNode *node); 70 | 71 | // Type check string literal node 72 | void slitTypeCheck(TypeCheckState *pstate, SLitNode *node); 73 | 74 | int litIsLiteral(INode* node); 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /src/c-compiler/ir/instype.h: -------------------------------------------------------------------------------- 1 | /** Shared logic for namespace-based types 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #ifndef instype_h 9 | #define instype_h 10 | 11 | // Namespaced type that supports named nodes (e.g., methods) and traits 12 | #define INsTypeNodeHdr \ 13 | ITypeNodeHdr; \ 14 | NodeList nodelist; \ 15 | Namespace namespace; \ 16 | INode *dropfn 17 | 18 | // Interface for a namespaced type 19 | // -> nodes (NodeList) is the list of nodes 20 | // -> namespace is the dictionary of names (methods, fields) 21 | // -> subtypes (Nodes) is the list of trait/interface subtypes it implements 22 | typedef struct INsTypeNode { 23 | INsTypeNodeHdr; 24 | } INsTypeNode; 25 | 26 | // Needed for helper functions 27 | typedef struct FnDclNode FnDclNode; 28 | typedef struct VarDclNode VarDclNode; 29 | 30 | // Initialize common fields 31 | void iNsTypeInit(INsTypeNode *type, int nodecnt); 32 | 33 | // Add a static function or potentially overloaded method to dictionary 34 | // If method is overloaded, add it to the link chain of same named methods 35 | void iNsTypeAddFnDict(INsTypeNode *type, FnDclNode *fnnode); 36 | 37 | // Add a function/method to type's dictionary and owned list 38 | void iNsTypeAddFn(INsTypeNode *type, FnDclNode *fnnode); 39 | 40 | // Find the named node (could be method or field) 41 | // Return the node, if found or NULL if not found 42 | INode *iNsTypeFindFnField(INsTypeNode *type, Name *name); 43 | 44 | // Find method that best fits the passed arguments 45 | // 'firstmethod' is the first method that matches the name 46 | // We follow its forward links to find one whose parameter types best match args types 47 | // isvref skips type checking of the 'self' parameter for virtual references 48 | FnDclNode *iNsTypeFindBestMethod(FnDclNode *firstmethod, INode **self, Nodes *args); 49 | 50 | // Find method whose method signature matches exactly (except for self) 51 | // return NULL if none 52 | FnDclNode *iNsTypeFindVrefMethod(FnDclNode *firstmeth, FnDclNode *matchmeth); 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /src/c-compiler/ir/types/permission.h: -------------------------------------------------------------------------------- 1 | /** Permission types 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #ifndef permission_h 9 | #define permission_h 10 | 11 | typedef struct NameUseNode NameUseNode; 12 | 13 | // Permission type info 14 | typedef struct PermNode { 15 | INsTypeNodeHdr; 16 | Name *namesym; 17 | uint16_t permflags; 18 | } PermNode; 19 | 20 | // Permission type flags 21 | // - Each true flag indicates a helpful capability the permission makes possible 22 | // - All false flags essentially deny those capabilities to the permission 23 | #define MayRead 0x01 // If on, the contents may be read 24 | #define MayWrite 0x02 // If on, the contents may be mutated 25 | // If on, another live alias may be created able to read or mutate the contents. 26 | // If off, any new alias turns off use of the old alias for the lifetime of the new alias. 27 | #define MayAlias 0x04 28 | #define MayAliasWrite 0x08 // If on, another live alias may be created able to write the contents. 29 | #define RaceSafe 0x10 // If on, a reference may be shared with or sent to another thread. 30 | // If on, interior references may be made within a sum type 31 | #define MayIntRefSum 0x20 32 | // If on, no locks are needed to read or mutate the contents. 33 | // If off, the permission's designated locking mechanism must be wrapped around all content access. 34 | #define IsLockless 0x40 35 | 36 | // Create a new permission declaration node 37 | PermNode *newPermDclNode(Name *namesym, uint16_t flags); 38 | 39 | // Create a new permission use node 40 | INode *newPermUseNode(PermNode *permdcl); 41 | 42 | // Serialize a permission node 43 | void permPrint(PermNode *node); 44 | 45 | // Get permission's flags 46 | int permGetFlags(INode *perm); 47 | 48 | // Are the permissions the same? 49 | int permIsSame(INode *node1, INode *node2); 50 | 51 | // Will 'from' permission coerce to the target? 52 | int permMatches(INode *to, INode *from); 53 | 54 | // Verify that permission init is correctly declared 55 | void permInitTypeCheck(INode *perm); 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /src/c-compiler/ir/nametbl.h: -------------------------------------------------------------------------------- 1 | /** Hashed name table 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #ifndef nametbl_h 9 | #define nametbl_h 10 | 11 | #include "ir.h" 12 | 13 | #include 14 | 15 | // The Global Name Table holds a context-spacific collection of names. 16 | // - Parse uses it to resolve: 17 | // - reserved keywords 18 | // - permission names that begin a declaration of a variable. 19 | // - allocator names as part of a reference type 20 | // - Name resolution uses it (see "hook" functions) to resolve: 21 | // - NameUse nodes to the name declaration node that they refer to 22 | 23 | // Global Name Table configuration variables 24 | extern size_t gNameTblInitSize; // Initial maximum number of unique names (must be power of 2) 25 | extern unsigned int gNameTblUtil; // % utilization that triggers doubling of table 26 | 27 | // Allocate and initialize the global name table 28 | void nametblInit(); 29 | 30 | // Get pointer to the Name struct for the name's string in the global name table 31 | // For an unknown name, it allocates memory for the string and adds it to name table. 32 | Name *nametblFind(char *strp, size_t strl); 33 | 34 | // Return how many bytes have been allocated for global name table but not yet used 35 | size_t nametblUnused(); 36 | 37 | // The global name hook functions help with the name resolution pass. 38 | // Whenever we enter a namespace context, the context's names are temporarily 39 | // added to the global name table. This way the lookup of a NameUse node 40 | // will find the innermost scope's node that declares this name. 41 | // Sometimes all of the namespace's names are added right away. 42 | // However, a block's local variables are added as encountered. 43 | // When the context ends, its names are unhooked, revealing the ones there before. 44 | void nametblHookPush(); 45 | void nametblHookGrow(); 46 | void nametblHookNode(Name *name, INode *node); 47 | // Hook all of a namespace's names and nodes in the current hooktable 48 | void nametblHookNamespace(Namespace *ns); 49 | void nametblHookPop(); 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /src/c-compiler/ir/types/fnsig.h: -------------------------------------------------------------------------------- 1 | /** Handling for function signature 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #ifndef fnsig_h 9 | #define fnsig_h 10 | 11 | typedef struct FnCallNode FnCallNode; 12 | 13 | // Function signature is a type that defines the parameters and return type for a function. 14 | // A function signature is never named (although a ptr/ref to a fnsig may be named). 15 | // The parameter declaration list represents a namespace of local variables. 16 | typedef struct FnSigNode { 17 | INodeHdr; 18 | Nodes *parms; // Declared parameter nodes w/ defaults (VarDclTag) 19 | INode *rettype; // void, a single type or a type tuple 20 | } FnSigNode; 21 | 22 | FnSigNode *newFnSigNode(); 23 | 24 | // Clone function signature 25 | INode *cloneFnSigNode(CloneState *cstate, FnSigNode *node); 26 | 27 | void fnSigPrint(FnSigNode *node); 28 | // Name resolution of the function signature 29 | void fnSigNameRes(NameResState *pstate, FnSigNode *sig); 30 | void fnSigTypeCheck(TypeCheckState *pstate, FnSigNode *name); 31 | int fnSigEqual(FnSigNode *node1, FnSigNode *node2); 32 | 33 | // For virtual reference structural matches on two methods, 34 | // compare two function signatures to see if they are equivalent, 35 | // ignoring the first 'self' parameter (we know their types differ) 36 | int fnSigVrefEqual(FnSigNode *node1, FnSigNode *node2); 37 | 38 | // Return TypeCompare indicating whether from type matches the function signature 39 | TypeCompare fnSigMatches(FnSigNode *to, FnSigNode *from, SubtypeConstraint constraint); 40 | 41 | // Return true if type of from-exp matches totype 42 | int fnSigCoerce(FnSigNode *totype, INode **fromexp); 43 | 44 | // Will the function call (caller) be able to call the 'to' function 45 | // Return 0 if not. 1 if perfect match. 2+ for imperfect matches 46 | int fnSigMatchesCall(FnSigNode *to, Nodes *args); 47 | 48 | // Will the method call (caller) be able to call the 'to' function 49 | // Return 0 if not. 1 if perfect match. 2+ for imperfect matches 50 | // if skipfirst is on, don't type check first argument for a vref 51 | int fnSigMatchMethCall(FnSigNode *to, INode **self, Nodes *args); 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /src/c-compiler/coneopts.h: -------------------------------------------------------------------------------- 1 | /** Cone compiler options 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #ifndef coneopts_h 9 | #define coneopts_h 10 | 11 | #include 12 | #include 13 | 14 | // Compiler options 15 | typedef struct ConeOptions { 16 | 17 | char **package_search_paths; 18 | char **safe_packages; 19 | // magic_package_t* magic_packages; 20 | 21 | char* srcpath; // Full path 22 | char* srcname; // Just the filename 23 | 24 | char* output; 25 | char* link_arch; 26 | char* linker; 27 | 28 | char* triple; 29 | char* cpu; 30 | char* features; 31 | 32 | //typecheck_t check; 33 | 34 | void* data; // User-defined data for unit test callbacks 35 | 36 | int ptrsize; // Size of a pointer (in bits) 37 | 38 | // Boolean flags 39 | int wasm; // 1=WebAssembly 40 | int release; // 0=debug (no optimizations). 1=release (default) 41 | int library; // 1=generate a C-API compatible static library 42 | int runtimebc; // Compile with the LLVM bitcode file for the runtime 43 | int pic; // Compile using position independent code 44 | int print_stats; // Print some compiler statistics 45 | int verify; // Verify LLVM IR 46 | int extfun; // Set function default linkage to external 47 | int simple_builtin; // Use a minimal builtin package 48 | int strip_debug; // Strip debug info 49 | int print_filenames; // Print source file names as each is processed 50 | int print_ir; // Print out IR 51 | int print_asm; // Print out assembly file 52 | int print_llvmir; // Print out LLVM IR 53 | int check_tree; // Verify IR well-formedness 54 | int lint_llvm; // Run the LLVM linting pass on generated IR 55 | int docs; // Generate code documentation 56 | int docs_private; // Generate code docs for private 57 | int verbosity; // 0 - 4 (0 = default) 58 | 59 | // verbosity_level verbosity; 60 | 61 | size_t ir_print_width; 62 | int allow_test_symbols; 63 | int parse_trace; 64 | } ConeOptions; 65 | 66 | int coneOptSet(ConeOptions *opt, int *argc, char **argv); 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /src/c-compiler/shared/timer.c: -------------------------------------------------------------------------------- 1 | /** Timer Handling 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #include 9 | #include 10 | #include "timer.h" 11 | 12 | size_t timerCurrent = TimerCount; 13 | uint64_t timerStamp = 0; 14 | uint64_t timers[TimerCount]; 15 | 16 | #if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) 17 | #include 18 | uint64_t timerGet() { 19 | LARGE_INTEGER captureTime; 20 | QueryPerformanceCounter(&captureTime); 21 | return (uint64_t)captureTime.QuadPart; 22 | } 23 | uint64_t timerTick() { 24 | LARGE_INTEGER captureFreq; 25 | QueryPerformanceFrequency(&captureFreq); 26 | return (uint64_t)captureFreq.QuadPart; 27 | } 28 | #else 29 | #include 30 | uint64_t timerGet() { 31 | struct timespec tp; 32 | clock_gettime(CLOCK_REALTIME, &tp); 33 | return (uint64_t)tp.tv_nsec; 34 | } 35 | uint64_t timerTick() { 36 | return 1000000000; 37 | } 38 | #endif 39 | 40 | void timerBegin(size_t aTimer) { 41 | uint64_t timer = timerGet(); 42 | if (timerCurrent < TimerCount) 43 | timers[timerCurrent] += timer - timerStamp; 44 | timerStamp = timer; 45 | timerCurrent = aTimer; 46 | } 47 | 48 | uint64_t timerGetTicks(size_t aTimer) { 49 | return timers[aTimer]; 50 | } 51 | 52 | double timerGetSecs(size_t aTimer) { 53 | return (double)timers[aTimer] / timerTick(); 54 | } 55 | 56 | double timerSummary() { 57 | uint64_t total = 0; 58 | for (int i = 0; i < TimerCount; ++i) 59 | total += timers[i]; 60 | return (double)total / timerTick(); 61 | } 62 | 63 | void timerPrint() { 64 | printf("Compile stage timing benchmarks (secs):\n"); 65 | printf(" LLVM setup: %.6g\n", timerGetSecs(SetupTimer)); 66 | printf(" Load: %.6g\n", timerGetSecs(LoadTimer)); 67 | printf(" Lexer: %.6g\n", timerGetSecs(LexTimer)); 68 | printf(" Parse: %.6g\n", timerGetSecs(ParseTimer)); 69 | printf(" Analysis %.6g\n", timerGetSecs(SemTimer)); 70 | printf(" Gen: %.6g\n", timerGetSecs(GenTimer)); 71 | printf(" Verify: %.6g\n", timerGetSecs(VerifyTimer)); 72 | printf(" Optimize: %.6g\n", timerGetSecs(OptTimer)); 73 | printf(" Codegen: %.6g\n", timerGetSecs(CodeGenTimer)); 74 | puts(""); 75 | } 76 | -------------------------------------------------------------------------------- /src/c-compiler/ir/exp/logic.c: -------------------------------------------------------------------------------- 1 | /** Handling for logic nodes 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #include "../ir.h" 9 | 10 | // Create a new logic operator node 11 | LogicNode *newLogicNode(int16_t typ) { 12 | LogicNode *node; 13 | newNode(node, LogicNode, typ); 14 | node->vtype = (INode*)boolType; 15 | return node; 16 | } 17 | 18 | // Clone logic node 19 | INode *cloneLogicNode(CloneState *cstate, LogicNode *node) { 20 | LogicNode *newnode; 21 | newnode = memAllocBlk(sizeof(LogicNode)); 22 | memcpy(newnode, node, sizeof(LogicNode)); 23 | newnode->lexp = cloneNode(cstate, node->lexp); 24 | newnode->rexp = cloneNode(cstate, node->rexp); 25 | return (INode *)newnode; 26 | } 27 | 28 | // Serialize logic node 29 | void logicPrint(LogicNode *node) { 30 | if (node->tag == NotLogicTag) { 31 | inodeFprint("!"); 32 | inodePrintNode(node->lexp); 33 | } 34 | else { 35 | inodeFprint(node->tag == AndLogicTag? "(&&, " : "(||, "); 36 | inodePrintNode(node->lexp); 37 | inodeFprint(", "); 38 | inodePrintNode(node->rexp); 39 | inodeFprint(")"); 40 | } 41 | } 42 | 43 | // Name resolution of not logic node 44 | void logicNotNameRes(NameResState *pstate, LogicNode *node) { 45 | inodeNameRes(pstate, &node->lexp); 46 | } 47 | 48 | // Type check not logic node 49 | void logicNotTypeCheck(TypeCheckState *pstate, LogicNode *node) { 50 | if (0 == iexpTypeCheckCoerce(pstate, (INode*)boolType, &node->lexp)) 51 | errorMsgNode(node->lexp, ErrorInvType, "Conditional expression must be coercible to boolean value."); 52 | } 53 | 54 | // Name resolution of logic node 55 | void logicNameRes(NameResState *pstate, LogicNode *node) { 56 | inodeNameRes(pstate, &node->lexp); 57 | inodeNameRes(pstate, &node->rexp); 58 | } 59 | 60 | // Analyze logic node 61 | void logicTypeCheck(TypeCheckState *pstate, LogicNode *node) { 62 | if (0 == iexpTypeCheckCoerce(pstate, (INode*)boolType, &node->lexp)) 63 | errorMsgNode(node->lexp, ErrorInvType, "Conditional expression must be coercible to boolean value."); 64 | if (0 == iexpTypeCheckCoerce(pstate, (INode*)boolType, &node->rexp)) 65 | errorMsgNode(node->rexp, ErrorInvType, "Conditional expression must be coercible to boolean value."); 66 | } 67 | -------------------------------------------------------------------------------- /src/c-compiler/ir/stmt/break.c: -------------------------------------------------------------------------------- 1 | /** Handling for break nodes 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #include "../ir.h" 9 | 10 | // Create a new break breaknode 11 | BreakRetNode *newBreakNode() { 12 | BreakRetNode *node; 13 | newNode(node, BreakRetNode, BreakTag); 14 | node->life = NULL; 15 | node->block = NULL; 16 | node->exp = NULL; 17 | node->dealias = NULL; 18 | return node; 19 | } 20 | 21 | // Clone break 22 | INode *cloneBreakNode(CloneState *cstate, BreakRetNode *node) { 23 | BreakRetNode *newnode; 24 | newnode = memAllocBlk(sizeof(BreakRetNode)); 25 | memcpy(newnode, node, sizeof(BreakRetNode)); 26 | newnode->exp = cloneNode(cstate, node->exp); 27 | newnode->block = (BlockNode *)cloneDclFix((INode*)node->block); 28 | return (INode *)newnode; 29 | } 30 | 31 | // Name resolution for break 32 | // - Resolve any lifetime or expression names 33 | void breakNameRes(NameResState *nstate, BreakRetNode *breaknode) { 34 | inodeNameRes(nstate, &breaknode->exp); 35 | 36 | // Resolve break to block it applies to 37 | if (breaknode->life) { 38 | // If a lifetime was specified, resolve to lifetime-named block 39 | inodeNameRes(nstate, &breaknode->life); 40 | BlockNode *block = (BlockNode*)((NameUseNode*)(breaknode->life))->dclnode; 41 | if (block && block->tag == BlockTag) { 42 | breaknode->block = block; 43 | } 44 | else { 45 | errorMsgNode((INode*)breaknode, ErrorNoLoop, "break's lifetime not found on a lifetime-named block"); 46 | } 47 | } 48 | else { 49 | // If no lifetime specified, resolve to inner-most loop block 50 | if (nstate->loopblock) 51 | breaknode->block = nstate->loopblock; 52 | else 53 | errorMsgNode((INode*)breaknode, ErrorNoLoop, "break may only be used within a while/each/loop block"); 54 | } 55 | } 56 | 57 | // Type check the break expression, ensure it matches loop's type 58 | void breakTypeCheck(TypeCheckState *pstate, BreakRetNode *breaknode) { 59 | 60 | // Note: we don't type check the break expression until later (as part of block type check), 61 | // when we can ensure all of them match to each other and whatever is expected 62 | nodesAdd(&breaknode->block->breaks, (INode*)breaknode); 63 | } 64 | -------------------------------------------------------------------------------- /src/c-compiler/ir/flow.h: -------------------------------------------------------------------------------- 1 | /** The Data Flow analysis pass whose purpose is to: 2 | 3 | * - Drop and free (or de-alias) variables at the end of their declared scope. 4 | * - Allow unique references to (conditionally) "escape" their current scope, 5 | thereby delaying when to drop and free/de-alias them. 6 | * - Track when copies (aliases) are made of a reference 7 | * - Ensure that lifetime-constrained borrowed references always outlive their containers. 8 | * - Deactivate variable bindings as a result of "move" semantics or 9 | * for the lifetime of their borrowed references. 10 | * - Enforce reference (and variable) mutability and aliasing permissions 11 | * - Track whether every variable has been initialized and used 12 | * 13 | * @file 14 | * 15 | * This source file is part of the Cone Programming Language C compiler 16 | * See Copyright Notice in conec.h 17 | */ 18 | 19 | #ifndef flow_h 20 | #define flow_h 21 | 22 | typedef struct VarDclNode VarDclNode; 23 | typedef struct FnSigNode FnSigNode; 24 | 25 | // Context used across the data flow pass for a specific function/method 26 | typedef struct FlowState { 27 | FnSigNode *fnsig; // The type signature of the function we are within 28 | int16_t scope; // Current block scope (2 = main block) 29 | } FlowState; 30 | 31 | // Perform data flow analysis on a node whose value we intend to load 32 | // At minimum, we check that it is a valid, readable value 33 | // copyflag indicates whether value is to be copied or moved 34 | // If copied, we may need to alias it. If moved, we may have to deactivate its source. 35 | void flowLoadValue(FlowState *fstate, INode **nodep); 36 | 37 | // Add a just declared variable to the data flow stack 38 | void flowAddVar(VarDclNode *varnode); 39 | 40 | // Start a new scope 41 | size_t flowScopePush(); 42 | 43 | // Create de-alias list of all own/rc reference variables, except var found in retexp 44 | // As a simple optimization: returns 1 if retexp name was not de-aliased 45 | int flowScopeDealias(size_t pos, Nodes **varlist, INode *retexp); 46 | // Back out of current scope 47 | void flowScopePop(size_t pos); 48 | 49 | // Alias Node structure 50 | typedef struct { 51 | IExpNodeHdr; 52 | INode *exp; 53 | int16_t *counts; // points to array of counts. NULL if not tuple 54 | int16_t aliasamt; // count nbr if not a tuple, # of counts if tuple 55 | } AliasNode; 56 | 57 | // Handle when moving or copying a value to a new destination 58 | void flowHandleMoveOrCopy(INode **nodep); 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /src/c-compiler/ir/types/number.c: -------------------------------------------------------------------------------- 1 | /** Handling for primitive numbers 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #include "../ir.h" 9 | 10 | // Clone number node 11 | INode *cloneNbrNode(CloneState *cstate, NbrNode *node) { 12 | NbrNode *newnode = memAllocBlk(sizeof(NbrNode)); 13 | memcpy(newnode, node, sizeof(NbrNode)); 14 | return (INode *)newnode; 15 | } 16 | 17 | // Serialize a numeric literal node 18 | void nbrTypePrint(NbrNode *node) { 19 | if (node == i8Type) 20 | inodeFprint("i8"); 21 | else if (node == i16Type) 22 | inodeFprint("i16"); 23 | else if (node == i32Type) 24 | inodeFprint("i32"); 25 | else if (node == i64Type) 26 | inodeFprint("i64"); 27 | else if (node == u8Type) 28 | inodeFprint("u8"); 29 | else if (node == u16Type) 30 | inodeFprint("u16"); 31 | else if (node == u32Type) 32 | inodeFprint("u32"); 33 | else if (node == u64Type) 34 | inodeFprint("u64"); 35 | else if (node == f32Type) 36 | inodeFprint("f32"); 37 | else if (node == f64Type) 38 | inodeFprint("f64"); 39 | else if (node == boolType) 40 | inodeFprint("Bool"); 41 | } 42 | 43 | // Is a number-typed node 44 | int isNbr(INode *node) { 45 | return (node->tag == IntNbrTag || node->tag == UintNbrTag || node->tag == FloatNbrTag); 46 | } 47 | 48 | // Return a type that is the supertype of both type nodes, or NULL if none found 49 | INode *nbrFindSuper(INode *type1, INode *type2) { 50 | NbrNode *typ1 = (NbrNode *)itypeGetTypeDcl(type1); 51 | NbrNode *typ2 = (NbrNode *)itypeGetTypeDcl(type2); 52 | 53 | return typ1->bits >= typ2->bits ? type1 : type2; 54 | } 55 | 56 | // Is from-type a subtype of to-struct (we know they are not the same) 57 | TypeCompare nbrMatches(INode *totype, INode *fromtype, SubtypeConstraint constraint) { 58 | // If coming from a ref, we cannot support type conversion 59 | if (constraint != Monomorph && constraint != Coercion) 60 | return NoMatch; 61 | 62 | // Bool is handled as a special case (also see iexpMatches) 63 | if (totype == (INode*)boolType) 64 | return NoMatch; 65 | 66 | if (totype->tag != fromtype->tag) 67 | return NoMatch; 68 | if (((NbrNode *)totype)->bits == ((NbrNode *)fromtype)->bits) 69 | return EqMatch; 70 | return ((NbrNode *)totype)->bits > ((NbrNode *)fromtype)->bits ? ConvSubtype : NoMatch; 71 | } 72 | -------------------------------------------------------------------------------- /src/c-compiler/ir/exp/nameuse.h: -------------------------------------------------------------------------------- 1 | /** Name and Member Use Nodes 2 | * 3 | * This source file is part of the Cone Programming Language C compiler 4 | * See Copyright Notice in conec.h 5 | */ 6 | 7 | #ifndef nameuse_h 8 | #define nameuse_h 9 | 10 | typedef struct NameList NameList; 11 | 12 | // Name use node, which ultimately points to the applicable declaration for the name 13 | // The node's name may optionally include module name qualifiers. Used by: 14 | // - NameUseTag. A name token prior to name resolution pass 15 | // - VarNameUseTag. A name use node resolved to a variable or function declaration 16 | // - TypeNameUseTag. A name use node resolved to a type declaration 17 | // - MbrNameUseTag. A method or field name being applied to some value 18 | typedef struct NameUseNode { 19 | IExpNodeHdr; 20 | Name *namesym; // Pointer to the global name table entry 21 | INode *dclnode; // Node that declares this name (NULL until names are resolved) 22 | NameList *qualNames; // Pointer to list of module qualifiers (NULL if none) 23 | } NameUseNode; 24 | 25 | NameUseNode *newNameUseNode(Name *name); 26 | 27 | // Create a working variable for a value we intend to reuse later 28 | // The vardcl is appended to a list of nodes, and the nameuse node to it is returned 29 | INode *newNameUseAndDcl(Nodes **nodesp, INode *val, uint16_t scope); 30 | 31 | // Create a new nameuse node pointing to an existing dclnode 32 | INode *newNameUseFromDclNode(INode *dclnode, INode *lexnode); 33 | 34 | // Clone NameUse 35 | INode *cloneNameUseNode(CloneState *cstate, NameUseNode *node); 36 | 37 | void nameUseBaseMod(NameUseNode *node, ModuleNode *basemod); 38 | void nameUseAddQual(NameUseNode *node, Name *name); 39 | NameUseNode *newMemberUseNode(Name *namesym); 40 | void nameUsePrint(NameUseNode *name); 41 | // Handle name resolution for name use references 42 | // - Point to name declaration in other module or this one 43 | // - If name is for a method or field, rewrite node as 'self.field' 44 | // - If not method/field, re-tag it as either TypeNameUse or VarNameUse 45 | void nameUseNameRes(NameResState *pstate, NameUseNode **namep); 46 | 47 | // Handle type check for variable/function name use references 48 | void nameUseTypeCheck(TypeCheckState *pstate, NameUseNode **name); 49 | 50 | // Handle type check for type name use references 51 | void nameUseTypeCheckType(TypeCheckState *pstate, NameUseNode **name); 52 | 53 | // Handle flow checking for nameuse 54 | void nameuseFlow(FlowState *fstate, NameUseNode **nodep); 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /src/c-compiler/ir/types/ttuple.c: -------------------------------------------------------------------------------- 1 | /** Handling for type tuple nodes 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #include "../ir.h" 9 | 10 | // Create a new type tuple node 11 | TupleNode *newTupleNode(int cnt) { 12 | TupleNode *tuple; 13 | newNode(tuple, TupleNode, TupleTag); 14 | tuple->elems = newNodes(cnt); 15 | return tuple; 16 | } 17 | 18 | // Clone tuple 19 | INode *cloneTupleNode(CloneState *cstate, TupleNode *node) { 20 | TupleNode *newnode; 21 | newnode = memAllocBlk(sizeof(TupleNode)); 22 | memcpy(newnode, node, sizeof(TupleNode)); 23 | newnode->elems = cloneNodes(cstate, node->elems); 24 | return (INode *)newnode; 25 | } 26 | 27 | // Serialize a type tuple node 28 | void ttuplePrint(TupleNode *tuple) { 29 | INode **nodesp; 30 | uint32_t cnt; 31 | 32 | for (nodesFor(tuple->elems, cnt, nodesp)) { 33 | inodePrintNode(*nodesp); 34 | if (cnt) 35 | inodeFprint(","); 36 | } 37 | } 38 | 39 | // Name resolution of the type tuple node 40 | void ttupleNameRes(NameResState *pstate, TupleNode *tuple) { 41 | int tag = -1; 42 | INode **nodesp; 43 | uint32_t cnt; 44 | for (nodesFor(tuple->elems, cnt, nodesp)) { 45 | inodeNameRes(pstate, nodesp); 46 | int newtag = isTypeNode(*nodesp) ? TTupleTag : VTupleTag; 47 | if (tag == -1) 48 | tag = newtag; 49 | else if (tag == -2) 50 | ; 51 | else if (tag != newtag) 52 | tag = -2; 53 | } 54 | if (tag >= 0) 55 | tuple->tag = tag; 56 | else 57 | errorMsgNode((INode*)tuple, ErrorBadElems, "Elements of tuple must be all types or all values"); 58 | } 59 | 60 | // Type check the type tuple node 61 | void ttupleTypeCheck(TypeCheckState *pstate, TupleNode *tuple) { 62 | INode **nodesp; 63 | uint32_t cnt; 64 | for (nodesFor(tuple->elems, cnt, nodesp)) 65 | itypeTypeCheck(pstate, nodesp); 66 | } 67 | 68 | // Compare that two tuples are equivalent 69 | int ttupleEqual(TupleNode *totype, TupleNode *fromtype) { 70 | if (fromtype->tag != TTupleTag) 71 | return 0; 72 | if (totype->elems->used != fromtype->elems->used) 73 | return 0; 74 | 75 | INode **fromnodesp = &nodesGet(fromtype->elems, 0); 76 | INode **nodesp; 77 | uint32_t cnt; 78 | for (nodesFor(totype->elems, cnt, nodesp)) 79 | if (!itypeIsSame(*nodesp, *fromnodesp++)) 80 | return 0; 81 | return 1; 82 | } 83 | -------------------------------------------------------------------------------- /src/c-compiler/ir/exp/fncall.h: -------------------------------------------------------------------------------- 1 | /** Handling for expression nodes that might do copy/move 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #ifndef fncall_h 9 | #define fncall_h 10 | 11 | // Function or method call node. Also used for array indexing and field access. 12 | // The parsed contents is lowered during type checking, potentially turning 13 | // it into an ArrIndexTag or FldAccessTag node 14 | typedef struct FnCallNode { 15 | IExpNodeHdr; 16 | INode *objfn; // Object (for method calls) or function to call 17 | INode *methfld; // Method or field node after '.' operator (typically MbrNameUseNode or NULL) 18 | Nodes *args; // List of function call arguments (or NULL) 19 | } FnCallNode; 20 | 21 | FnCallNode *newFnCallNode(INode *objfn, int nnodes); 22 | // Create new fncall node, prefilling method, self, and creating room for nnodes args 23 | FnCallNode *newFnCallOpname(INode *obj, Name *opname, int nnodes); 24 | FnCallNode *newFnCallOp(INode *obj, char *op, int nnodes); 25 | FnCallNode *newFnCallLower(INode *oldnode, INode *obj, int nnodes); 26 | 27 | // Clone fncall 28 | INode *cloneFnCallNode(CloneState *cstate, FnCallNode *node); 29 | 30 | void fnCallPrint(FnCallNode *node); 31 | 32 | // Name resolution on 'fncall' 33 | // - If node is indexing on a type, retag node as a typelit 34 | // Note: this never name resolves .methfld, which is handled in type checking 35 | void fnCallNameRes(NameResState *pstate, FnCallNode **nodep); 36 | 37 | // Type check on fncall 38 | void fnCallTypeCheck(TypeCheckState *pstate, FnCallNode **node); 39 | 40 | // Find best field or method (across overloaded methods whose type matches argument types) 41 | // Then lower the node to a function call (objfn+args) or field access (objfn+methfld) accordingly 42 | int fnCallLowerMethod(FnCallNode *callnode); 43 | 44 | // We have a reference or pointer, and a method to find (comparison or arithmetic) 45 | // If found, lower the node to a function call (objfn+args) 46 | // Otherwise try again against the type it points to 47 | int fnCallLowerPtrMethod(FnCallNode *callnode, INsTypeNode *methtype); 48 | 49 | // Do data flow analysis for fncall node (only real function calls) 50 | void fnCallFlow(FlowState *fstate, FnCallNode **nodep); 51 | 52 | // Perform data flow analysis on array index node 53 | void fnCallArrIndexFlow(FlowState *fstate, FnCallNode **node); 54 | 55 | // Perform data flow analysis on field access node 56 | void fnCallFldAccessFlow(FlowState *fstate, FnCallNode **node); 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /src/c-compiler/ir/stmt/const.c: -------------------------------------------------------------------------------- 1 | /** Handling for constant declaration nodes 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #include "../ir.h" 9 | 10 | #include 11 | #include 12 | 13 | // Create a new constant declaraction node 14 | ConstDclNode *newConstDclNode(Name *namesym) { 15 | ConstDclNode *name; 16 | newNode(name, ConstDclNode, ConstDclTag); 17 | name->vtype = unknownType; 18 | name->namesym = namesym; 19 | name->value = NULL; 20 | return name; 21 | } 22 | 23 | // Create a new constant dcl node that is a copy of an existing one 24 | INode *cloneConstDclNode(CloneState *cstate, ConstDclNode *node) { 25 | ConstDclNode *newnode = memAllocBlk(sizeof(ConstDclNode)); 26 | memcpy(newnode, node, sizeof(ConstDclNode)); 27 | newnode->vtype = cloneNode(cstate, node->vtype); 28 | newnode->value = cloneNode(cstate, node->value); 29 | cloneDclSetMap((INode*)node, (INode*)newnode); 30 | return (INode*)newnode; 31 | } 32 | 33 | // Serialize a constant node 34 | void constDclPrint(ConstDclNode *name) { 35 | inodeFprint("const %s ", &name->namesym->namestr); 36 | inodePrintNode(name->vtype); 37 | inodeFprint(" = "); 38 | if (name->value->tag == BlockTag) 39 | inodePrintNL(); 40 | inodePrintNode(name->value); 41 | } 42 | 43 | // Enable name resolution of local variables 44 | void constDclNameRes(NameResState *pstate, ConstDclNode *name) { 45 | if (name->vtype) 46 | inodeNameRes(pstate, &name->vtype); 47 | 48 | // Name resolve value before hooking the constant name (so it cannot point to itself) 49 | if (name->value) 50 | inodeNameRes(pstate, &name->value); 51 | 52 | } 53 | 54 | // Type check constant against its initial value 55 | void constDclTypeCheck(TypeCheckState *pstate, ConstDclNode *name) { 56 | if (itypeTypeCheck(pstate, &name->vtype) == 0) 57 | return; 58 | 59 | // An initializer need not be specified, but if not, it must have a declared type 60 | // Verify that declared type and initial value type match 61 | if (!iexpTypeCheckCoerce(pstate, name->vtype, &name->value)) 62 | errorMsgNode(name->value, ErrorInvType, "Initialization value's type does not match named constant's declared type"); 63 | else if (name->vtype == unknownType) 64 | name->vtype = ((IExpNode *)name->value)->vtype; 65 | // Constants must be literal 66 | if (!litIsLiteral(name->value)) 67 | errorMsgNode(name->value, ErrorNotLit, "Named constants must be assigned to a constant value."); 68 | } 69 | -------------------------------------------------------------------------------- /src/c-compiler/ir/stmt/swap.c: -------------------------------------------------------------------------------- 1 | /** Handling for swap nodes 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #include "../ir.h" 9 | 10 | #include 11 | 12 | // Create a new swap node 13 | SwapNode *newSwapNode(INode *lval, INode *rval) { 14 | SwapNode *node; 15 | newNode(node, SwapNode, SwapTag); 16 | node->lval = lval; 17 | node->rval = rval; 18 | return node; 19 | } 20 | 21 | // Clone swap node 22 | INode *cloneSwapNode(CloneState *cstate, SwapNode *node) { 23 | SwapNode *newnode; 24 | newnode = memAllocBlk(sizeof(SwapNode)); 25 | memcpy(newnode, node, sizeof(SwapNode)); 26 | newnode->lval = cloneNode(cstate, node->lval); 27 | newnode->rval = cloneNode(cstate, node->rval); 28 | return (INode *)newnode; 29 | } 30 | 31 | // Serialize swap node 32 | void swapPrint(SwapNode *node) { 33 | inodeFprint("(<=>, "); 34 | inodePrintNode(node->lval); 35 | inodeFprint(", "); 36 | inodePrintNode(node->rval); 37 | inodeFprint(")"); 38 | } 39 | 40 | // Name resolution for swap node 41 | void swapNameRes(NameResState *pstate, SwapNode *node) { 42 | inodeNameRes(pstate, &node->lval); 43 | inodeNameRes(pstate, &node->rval); 44 | } 45 | 46 | // Type checking for swap node 47 | void swapTypeCheck(TypeCheckState *pstate, SwapNode *node) { 48 | if (iexpTypeCheckAny(pstate, &node->lval) == 0 || iexpIsLvalError(node->lval) == 0) 49 | return; 50 | 51 | if (iexpTypeCheckAny(pstate, &node->rval) == 0 || iexpIsLvalError(node->rval) == 0) 52 | return; 53 | 54 | if (!iexpSameType(node->lval, &node->rval)) { 55 | errorMsgNode(node->lval, ErrorInvType, "Swap lvals do not have matching types"); 56 | return; 57 | } 58 | } 59 | 60 | // Perform data flow analysis on swap node 61 | // - lval and rval need to be mutable. 62 | void swapFlow(FlowState *fstate, SwapNode **nodep) { 63 | SwapNode *node = *nodep; 64 | 65 | uint16_t lvalscope; 66 | INode *lvalperm; 67 | INode *lvalvar = iexpGetLvalInfo(node->lval, &lvalperm, &lvalscope); 68 | if (!(MayWrite & permGetFlags(lvalperm))) { 69 | errorMsgNode(node->lval, ErrorNoMut, "You do not have permission to modify lval"); 70 | return; 71 | } 72 | 73 | lvalvar = iexpGetLvalInfo(node->rval, &lvalperm, &lvalscope); 74 | if (!(MayWrite & permGetFlags(lvalperm))) { 75 | errorMsgNode(node->rval, ErrorNoMut, "You do not have permission to modify rval"); 76 | return; 77 | } 78 | 79 | flowLoadValue(fstate, &node->lval); 80 | flowLoadValue(fstate, &node->rval); 81 | } 82 | -------------------------------------------------------------------------------- /src/c-compiler/ir/types/lifetime.c: -------------------------------------------------------------------------------- 1 | /** Lifetime Annotations (Variables) 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #include "../ir.h" 9 | 10 | #include 11 | 12 | // Create a new lifetime declaration node 13 | LifetimeNode *newLifetimeDclNode(Name *namesym, Lifetime life) { 14 | LifetimeNode *node; 15 | newNode(node, LifetimeNode, LifetimeTag); 16 | node->namesym = namesym; 17 | node->llvmtype = NULL; 18 | node->life = life; 19 | return node; 20 | } 21 | 22 | // Create a copy of lifetime dcl 23 | INode *cloneLifetimeDclNode(CloneState *cstate, LifetimeNode *node) { 24 | LifetimeNode *newnode = memAllocBlk(sizeof(LifetimeNode)); 25 | memcpy(newnode, node, sizeof(LifetimeNode)); 26 | newnode->life = cstate->scope; 27 | cloneDclSetMap((INode*)node, (INode*)newnode); 28 | return (INode*)newnode; 29 | } 30 | 31 | // Create a new lifetime use node 32 | INode *newLifetimeUseNode(LifetimeNode *lifedcl) { 33 | NameUseNode *life; 34 | newNode(life, NameUseNode, TypeNameUseTag); 35 | life->vtype = NULL; 36 | life->namesym = lifedcl->namesym; 37 | life->dclnode = (INode*)lifedcl; 38 | life->qualNames = NULL; 39 | return (INode*)life; 40 | } 41 | 42 | // Serialize a lifetime node 43 | void lifePrint(LifetimeNode *node) { 44 | inodeFprint("%s ", &node->namesym->namestr); 45 | } 46 | 47 | // Are the lifetimes the same? 48 | int lifeIsSame(INode *node1, INode *node2) { 49 | if (node1->tag == TypeNameUseTag) 50 | node1 = (INode*)((NameUseNode*)node1)->dclnode; 51 | if (node2->tag == TypeNameUseTag) 52 | node2 = (INode*)((NameUseNode*)node2)->dclnode; 53 | assert(node1->tag == LifetimeTag && node2->tag == LifetimeTag); 54 | return node1 == node2; 55 | } 56 | 57 | // Will 'from' lifetime coerce as a subtype to the target? 58 | int lifeMatches(INode *ito, INode *ifrom) { 59 | LifetimeNode *from = (LifetimeNode *)((ifrom->tag == TypeNameUseTag)? (INode*)((NameUseNode*)ifrom)->dclnode : ifrom); 60 | LifetimeNode *to = (LifetimeNode *)((ito->tag == TypeNameUseTag)? (INode*)((NameUseNode*)ito)->dclnode : ito); 61 | assert(from->tag == LifetimeTag && to->tag == LifetimeTag); 62 | 63 | // 'static is a supertype of all lifetimes 64 | if (to->life == 0) 65 | return 1; 66 | 67 | uint16_t fromgrp = from->life >> 8; 68 | uint16_t fromscope = from->life & 0xff; 69 | uint16_t togrp = to->life >> 8; 70 | uint16_t toscope = to->life & 0xff; 71 | 72 | return (fromscope >= toscope && (fromgrp == 0 || fromgrp == togrp)) ? 1 : 0; 73 | } 74 | -------------------------------------------------------------------------------- /src/c-compiler/ir/types/region.c: -------------------------------------------------------------------------------- 1 | /** Region type handling - region is a specialized struct 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #include "../ir.h" 9 | 10 | int isRegion(INode *region, Name *namesym) { 11 | region = itypeGetTypeDcl(region); 12 | if (region->tag == StructTag) { 13 | StructNode *rnode = (StructNode*)region; 14 | return rnode->namesym == namesym; 15 | } 16 | return 0; 17 | } 18 | 19 | int regionIsPtrU8(RefNode *ptrnode) { 20 | if (ptrnode->tag != PtrTag) 21 | return 0; 22 | NbrNode *nbrnode = (NbrNode*)itypeGetTypeDcl(ptrnode->vtexp); 23 | if (nbrnode != u8Type) 24 | return 0; 25 | return 1; 26 | } 27 | 28 | // Verify that region allocator exists and it (and init method) are correctly declared 29 | void regionAllocTypeCheck(INode *region) { 30 | if (region->tag != StructTag) { 31 | errorMsgNode(region, ErrorInvType, "Not a valid region."); 32 | return; 33 | } 34 | FnDclNode *allocmeth = (FnDclNode*)iTypeFindFnField(region, allocMethodName); 35 | if (allocmeth == NULL || allocmeth->tag != FnDclTag) { 36 | errorMsgNode(region, ErrorInvType, "Region does not support allocation as it lacks _alloc static method."); 37 | return; 38 | } 39 | FnSigNode *allocsig = (FnSigNode*)itypeGetTypeDcl(allocmeth->vtype); 40 | if (allocsig->parms->used != 1) { 41 | errorMsgNode((INode*)allocmeth, ErrorInvType, "Region _alloc method needs single usize parm."); 42 | return; 43 | } 44 | NbrNode *sizetype = (NbrNode *)itypeGetTypeDcl(iexpGetTypeDcl(nodesGet(allocsig->parms, 0))); 45 | if (sizetype != usizeType) { 46 | errorMsgNode((INode*)allocmeth, ErrorInvType, "Region _alloc method needs single usize parm."); 47 | return; 48 | } 49 | RefNode *rettype = (RefNode*)itypeGetTypeDcl(allocsig->rettype); 50 | if (!regionIsPtrU8(rettype)) { 51 | errorMsgNode((INode*)allocmeth, ErrorInvType, "Region _alloc method must return *u8."); 52 | return; 53 | } 54 | 55 | FnDclNode *initmeth = (FnDclNode*)iTypeFindFnField(region, initMethodName); 56 | if (initmeth == NULL) { 57 | return; 58 | } 59 | FnSigNode *initsig = (FnSigNode*)itypeGetTypeDcl(initmeth->vtype); 60 | if (initsig->parms->used != 0) { 61 | errorMsgNode((INode*)initmeth, ErrorInvType, "Region init method may not have parameters."); 62 | return; 63 | } 64 | INode *initrettype = itypeGetTypeDcl(initsig->rettype); 65 | if (itypeMatches(initrettype, region, Coercion) != EqMatch) { 66 | errorMsgNode((INode*)initmeth, ErrorInvType, "Region init method must return initial value."); 67 | return; 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/c-compiler/ir/name.c: -------------------------------------------------------------------------------- 1 | /** Name handling 2 | * 3 | * @file 4 | * 5 | * This source file is part of the Cone Programming Language C compiler 6 | * See Copyright Notice in conec.h 7 | */ 8 | 9 | #include "ir.h" 10 | #include "../shared/memory.h" 11 | 12 | #include 13 | #include 14 | 15 | Name *anonName; 16 | Name *tempName; 17 | Name *selfName; 18 | Name *selfTypeName; 19 | Name *thisName; 20 | Name *cloneName; 21 | Name *dropName; 22 | Name *finalName; 23 | Name *plusEqName; 24 | Name *minusEqName; 25 | Name *multEqName; 26 | Name *divEqName; 27 | Name *remEqName; 28 | Name *orEqName; 29 | Name *andEqName; 30 | Name *xorEqName; 31 | Name *shlEqName; 32 | Name *shrEqName; 33 | Name *lessDashName; 34 | Name *plusName; 35 | Name *minusName; 36 | Name *istrueName; 37 | Name *multName; 38 | Name *divName; 39 | Name *remName; 40 | Name *orName; 41 | Name *andName; 42 | Name *xorName; 43 | Name *shlName; 44 | Name *shrName; 45 | Name *incrName; 46 | Name *decrName; 47 | Name *incrPostName; 48 | Name *decrPostName; 49 | Name *eqName; 50 | Name *neName; 51 | Name *leName; 52 | Name *ltName; 53 | Name *geName; 54 | Name *gtName; 55 | Name *parensName; 56 | Name *indexName; 57 | Name *refIndexName; 58 | Name *corelibName; 59 | Name *optionName; 60 | Name *rcName; 61 | Name *soName; 62 | Name *allocMethodName; 63 | Name *initMethodName; 64 | 65 | void nameNewPrefix(char **prefix, char *name) { 66 | size_t size = strlen(name) + 1; 67 | char *newprefix = memAllocStr(name, size); 68 | strcat(newprefix, "_"); 69 | *prefix = newprefix; 70 | } 71 | 72 | void nameConcatPrefix(char **prefix, char *name) { 73 | size_t size = strlen(*prefix) + strlen(name) + 1; 74 | char *newprefix = memAllocStr(*prefix, size); 75 | strcat(newprefix, name); 76 | strcat(newprefix, "_"); 77 | *prefix = newprefix; 78 | } 79 | 80 | // Create globally unique variable name, prefixed by module/type name 81 | void nameGenVarName(VarDclNode *node, char *prefix) { 82 | // Known name is fine if extern or in main module 83 | if (*prefix == '\0' || (node->flags & FlagExtern)) 84 | return; 85 | 86 | char *namestr = node->genname; 87 | size_t size = strlen(prefix) + strlen(namestr); 88 | node->genname = memAllocStr(prefix, size); 89 | strcat(node->genname, namestr); 90 | } 91 | 92 | // Create globally unique function name, prefixed by module/type name 93 | // Note: Any necessary mangling will happen at gen time 94 | void nameGenFnName(FnDclNode *node, char *prefix) { 95 | // Known name is fine if extern or in main module 96 | if (*prefix == '\0' || (node->flags & FlagExtern)) 97 | return; 98 | 99 | char *namestr = node->genname; 100 | size_t size = strlen(prefix) + strlen(namestr); 101 | node->genname = memAllocStr(prefix, size); 102 | strcat(node->genname, namestr); 103 | } 104 | -------------------------------------------------------------------------------- /src/c-compiler/corelib/corelib.c: -------------------------------------------------------------------------------- 1 | /** Standard library initialization 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #include "../ir/ir.h" 9 | #include "../ir/nametbl.h" 10 | #include "../parser/lexer.h" 11 | 12 | #include 13 | 14 | INode *unknownType; 15 | INode *noCareType; 16 | INode *elseCond; 17 | INode *borrowRef; 18 | PermNode *uniPerm; 19 | PermNode *mutPerm; 20 | PermNode *immPerm; 21 | PermNode *roPerm; 22 | PermNode *mut1Perm; 23 | PermNode *opaqPerm; 24 | LifetimeNode *staticLifetimeNode; 25 | NbrNode *boolType; 26 | NbrNode *i8Type; 27 | NbrNode *i16Type; 28 | NbrNode *i32Type; 29 | NbrNode *i64Type; 30 | NbrNode *isizeType; 31 | NbrNode *u8Type; 32 | NbrNode *u16Type; 33 | NbrNode *u32Type; 34 | NbrNode *u64Type; 35 | NbrNode *usizeType; 36 | NbrNode *f32Type; 37 | NbrNode *f64Type; 38 | INsTypeNode *ptrType; 39 | INsTypeNode *refType; 40 | INsTypeNode *arrayRefType; 41 | 42 | PermNode *newPermNodeStr(char *name, uint16_t flags) { 43 | Name *namesym = nametblFind(name, strlen(name)); 44 | PermNode *perm = newPermDclNode(namesym, flags); 45 | namesym->node = (INode*)perm; 46 | return perm; 47 | } 48 | 49 | // Declare built-in permission types and their names 50 | void stdPermInit() { 51 | uniPerm = newPermNodeStr("uni", MayRead | MayWrite | RaceSafe | MayIntRefSum | IsLockless); 52 | mutPerm = newPermNodeStr("mut", MayRead | MayWrite | MayAlias | MayAliasWrite | IsLockless); 53 | immPerm = newPermNodeStr("imm", MayRead | MayAlias | RaceSafe | MayIntRefSum | IsLockless); 54 | roPerm = newPermNodeStr("ro", MayRead | MayAlias | IsLockless); 55 | mut1Perm = newPermNodeStr("mut1", MayRead | MayWrite | MayAlias | MayIntRefSum | IsLockless); 56 | opaqPerm = newPermNodeStr("opaq", MayAlias | RaceSafe | IsLockless); 57 | } 58 | 59 | char *corelibSource = 60 | "union Option[T] {\n" 61 | "struct None {}\n" 62 | "struct Some {value T}\n" 63 | "}\n" 64 | 65 | "union Result[T,E] {\n" 66 | "struct Ok {value T}\n" 67 | "struct Error {value E}\n" 68 | "}\n" 69 | 70 | "extern fn malloc(size usize) *u8\n" 71 | 72 | "struct @move so:\n" 73 | " fn _alloc(size usize) *u8 inline {malloc(size)}\n" 74 | 75 | "struct rc:\n" 76 | " cnt usize\n" 77 | " fn _alloc(size usize) *u8 inline {malloc(size)}\n" 78 | " fn init() rc inline {rc[1usize]}\n" 79 | ; 80 | 81 | // Set up the standard library, whose names are always shared by all modules 82 | void stdlibInit(int ptrsize) { 83 | 84 | unknownType = (INode*)newAbsenceNode(); 85 | unknownType->tag = UnknownTag; 86 | noCareType = (INode*)newAbsenceNode(); 87 | noCareType->tag = UnknownTag; 88 | elseCond = (INode*)newAbsenceNode(); 89 | borrowRef = (INode*)newAbsenceNode(); 90 | borrowRef->tag = BorrowRegTag; 91 | 92 | staticLifetimeNode = newLifetimeDclNode(nametblFind("'static", 7), 0); 93 | stdPermInit(); 94 | stdNbrInit(ptrsize); 95 | } 96 | -------------------------------------------------------------------------------- /src/c-compiler/ir/nodelist.c: -------------------------------------------------------------------------------- 1 | /** Shared logic for namespace-based types 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #include "ir.h" 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | // Initialize methnodes metadata 15 | void nodelistInit(NodeList *mnodes, uint32_t size) { 16 | mnodes->avail = size; 17 | mnodes->used = 0; 18 | mnodes->nodes = (INode **)memAllocBlk(size * sizeof(INode **)); 19 | } 20 | 21 | // Double size, if full 22 | void nodelistGrow(NodeList *mnodes) { 23 | INode **oldnodes; 24 | oldnodes = mnodes->nodes; 25 | mnodes->avail <<= 1; 26 | mnodes->nodes = (INode **)memAllocBlk(mnodes->avail * sizeof(INode **)); 27 | memcpy(mnodes->nodes, oldnodes, mnodes->used * sizeof(INode **)); 28 | } 29 | 30 | // Add an INode to the end of a NodeList, growing it if full (changing its memory location) 31 | void nodelistAdd(NodeList *mnodes, INode *node) { 32 | if (mnodes->used >= mnodes->avail) 33 | nodelistGrow(mnodes); 34 | mnodes->nodes[mnodes->used++] = node; 35 | } 36 | 37 | // Insert a node into a nodelist at pos 38 | void nodelistInsert(NodeList *mnodes, uint32_t pos, INode *node) { 39 | while (mnodes->used + 1 >= mnodes->avail) 40 | nodelistGrow(mnodes); 41 | memmove(&mnodes->nodes[pos + 1], &mnodes->nodes[pos], (mnodes->used - pos) * sizeof(INode *)); 42 | mnodes->nodes[pos] = node; 43 | mnodes->used += 1; 44 | } 45 | 46 | // Insert some list into another list, beginning at index 47 | void nodelistInsertList(NodeList *mnodes, NodeList *fromnodes, uint32_t index) { 48 | while (mnodes->used + fromnodes->used >= mnodes->avail) 49 | nodelistGrow(mnodes); 50 | uint32_t amt = fromnodes->used; 51 | memmove(&mnodes->nodes[amt + index], &mnodes->nodes[index], (mnodes->used-index) * sizeof(INode *)); 52 | memcpy(&mnodes->nodes[index], fromnodes->nodes, amt * sizeof(INode **)); 53 | mnodes->used += fromnodes->used; 54 | } 55 | 56 | // Open up space for amt new nodes beginning at pos. 57 | // If amt is negative, delete that number of nodes 58 | void nodelistMakeSpace(NodeList *nodes, size_t pos, int32_t amt) { 59 | if (amt == 0) 60 | return; 61 | // If full, double its size as much as needed 62 | if (nodes->used + amt >= nodes->avail) { 63 | uint32_t newsize = nodes->avail << 1; 64 | while (nodes->used + amt >= newsize) 65 | newsize <<= 1; 66 | INode **oldnodes = nodes->nodes; 67 | nodes->nodes = memAllocBlk(newsize); 68 | memcpy(nodes->nodes, oldnodes, (nodes->used) * sizeof(INode*)); 69 | } 70 | 71 | // Move nodes after pos up or down accordingly 72 | INode **posp = &nodes->nodes[pos]; 73 | if (amt > 0) 74 | memmove(posp + amt, posp, (nodes->used - pos) * sizeof(INode*)); 75 | else 76 | memmove(posp, posp - amt, (nodes->used - pos + amt) * sizeof(INode*)); 77 | nodes->used += amt; 78 | } 79 | -------------------------------------------------------------------------------- /src/c-compiler/ir/iexp.h: -------------------------------------------------------------------------------- 1 | /** Expression nodes that return a typed value 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #ifndef iexp_h 9 | #define iexp_h 10 | 11 | // Castable structure for all typed nodes 12 | typedef struct IExpNode { 13 | IExpNodeHdr; 14 | } IExpNode; 15 | 16 | // Return node's type's declaration node 17 | // (Note: only use after it has been type-checked) 18 | INode *iexpGetTypeDcl(INode *node); 19 | 20 | // Return node's type's declaration node 21 | // and when it is a a pointer/ref, get its type declaration node 22 | // (Note: only use after it has been type-checked) 23 | INode *iexpGetDerefTypeDcl(INode *node); 24 | 25 | // Type check node we expect to be an expression. Return 0 if not. 26 | int iexpTypeCheckAny(TypeCheckState *pstate, INode **from); 27 | 28 | // Return whether it is okay for from expression to be coerced to to-type 29 | TypeCompare iexpMatches(INode **from, INode *totype, SubtypeConstraint constraint); 30 | 31 | // Coerce from-node's type to 'to' expected type, if needed 32 | // Return 1 if type "matches", 0 otherwise 33 | int iexpCoerce(INode **from, INode *totypep); 34 | 35 | // Perform full type check on from-node and ensure it is an expression. 36 | // Then coerce from-node's type to 'to' expected type, if needed 37 | // Return 1 if type "matches", 0 otherwise 38 | int iexpTypeCheckCoerce(TypeCheckState *pstate, INode *to, INode **from); 39 | 40 | // Used by 'if' and 'loop' to infer the type in common across all branches, 41 | // one branch at a time. Errors on bad type match and returns Match condition. 42 | // - expectType is the final type expected by receiver 43 | // - maybeType is the inferred type in common 44 | // - from is the current branch whose type is being examined 45 | int iexpMultiInfer(INode *expectType, INode **maybeType, INode **from); 46 | 47 | // Used by 'if' and 'block/loop'/break to infer the type in common across all branches, 48 | // one branch at a time. Errors on bad type match and returns Match condition. 49 | // - expectType is the final type expected by receiver (or else don't care) 50 | // - inferredType is the inferred supertype in common 51 | // - fromexp is the current expression node whose type is being examined 52 | // - oldMatch is the current match status on whether all branches match or not 53 | int iexpMultiCoerceInfer(TypeCheckState *pstate, INode *expectType, INode **inferredType, INode **fromexp, int oldMatch); 54 | 55 | // Return true if an lval, and 0 if not. 56 | int iexpIsLval(INode *lval); 57 | 58 | // Ensure it is a lval, return error and 0 if not. 59 | int iexpIsLvalError(INode *lval); 60 | 61 | // Extract lval variable, scope and overall permission from lval 62 | INode *iexpGetLvalInfo(INode *lval, INode **lvalperm, uint16_t *scope); 63 | 64 | // Are types the same (no coercion) 65 | int iexpSameType(INode *to, INode **from); 66 | 67 | // Retrieve the permission flags for the node 68 | uint16_t iexpGetPermFlags(INode *node); 69 | 70 | // Return true if value uses move semantics 71 | int iexpIsMove(INode *node); 72 | 73 | #endif 74 | -------------------------------------------------------------------------------- /src/c-compiler/ir/types/reference.h: -------------------------------------------------------------------------------- 1 | /** Handling for reference types 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #ifndef reference_h 9 | #define reference_h 10 | 11 | // Metadata for normalized reference type 12 | typedef struct { 13 | LLVMTypeRef llvmtyperef; 14 | LLVMTypeRef structype; 15 | LLVMTypeRef ptrstructype; 16 | } RefTypeInfo; 17 | 18 | enum ManagedRefFields { 19 | RegionField, 20 | PermField, 21 | ValueField 22 | }; 23 | 24 | // Reference node: used for reference type, allocation or borrow node 25 | typedef struct { 26 | ITypeNodeHdr; 27 | INode *vtexp; // Value/type expression 28 | INode *perm; // Permission 29 | INode *region; // Region 30 | RefTypeInfo *typeinfo; // normalized ref info 31 | uint16_t scope; // Lifetime 32 | } RefNode; 33 | 34 | // Create a new reference type whose info will be filled in afterwards 35 | RefNode *newRefNode(uint16_t tag); 36 | 37 | // Allocate normalized reference type info 38 | void *refTypeInfoAlloc(); 39 | 40 | // Clone reference 41 | INode *cloneRefNode(CloneState *cstate, RefNode *node); 42 | 43 | // Create a new reference type whose info is known and analyzeable 44 | RefNode *newRefNodeFull(uint16_t tag, INode *lexnode, INode *region, INode *perm, INode *vtype); 45 | 46 | // Set the inferred value type of a reference 47 | void refSetPermVtype(RefNode *refnode, INode *perm, INode *vtype); 48 | 49 | // Create a new ArrayDerefNode from an ArrayRefNode 50 | RefNode *newArrayDerefNodeFrom(RefNode *refnode); 51 | 52 | // Serialize a reference type 53 | void refPrint(RefNode *node); 54 | 55 | // Name resolution of a reference node 56 | void refNameRes(NameResState *pstate, RefNode *node); 57 | 58 | // Type check a reference node 59 | void refTypeCheck(TypeCheckState *pstate, RefNode *name); 60 | 61 | // Type check a virtual reference node 62 | void refvirtTypeCheck(TypeCheckState *pstate, RefNode *node); 63 | 64 | // Compare two reference signatures to see if they are equivalent 65 | int refIsSame(RefNode *node1, RefNode *node2); 66 | 67 | // Calculate hash for a structural reference type 68 | size_t refHash(RefNode *node); 69 | 70 | // Compare two reference signatures to see if they are equivalent at runtime 71 | int refIsRunSame(RefNode *node1, RefNode *node2); 72 | 73 | // Will from region coerce to a to region 74 | TypeCompare regionMatches(INode *to, INode *from, SubtypeConstraint constraint); 75 | 76 | // Will from reference coerce to a to reference (we know they are not the same) 77 | TypeCompare refMatches(RefNode *to, RefNode *from, SubtypeConstraint constraint); 78 | 79 | // Will from reference coerce to a virtual reference (we know they are not the same) 80 | TypeCompare refvirtMatchesRef(RefNode *to, RefNode *from, SubtypeConstraint constraint); 81 | 82 | // Will from reference coerce to a virtual reference (we know they are not the same) 83 | TypeCompare refvirtMatches(RefNode *to, RefNode *from, SubtypeConstraint constraint); 84 | 85 | // Return a type that is the supertype of both type nodes, or NULL if none found 86 | INode *refFindSuper(INode *type1, INode *type2); 87 | 88 | #endif 89 | -------------------------------------------------------------------------------- /src/c-compiler/ir/stmt/fielddcl.c: -------------------------------------------------------------------------------- 1 | /** Handling for field declaration nodes 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #include "../ir.h" 9 | 10 | #include 11 | #include 12 | 13 | // Create a new name declaraction node 14 | FieldDclNode *newFieldDclNode(Name *namesym, INode *perm) { 15 | FieldDclNode *fldnode; 16 | newNode(fldnode, FieldDclNode, FieldDclTag); 17 | fldnode->vtype = unknownType; 18 | fldnode->namesym = namesym; 19 | fldnode->perm = perm; 20 | fldnode->value = NULL; 21 | fldnode->index = 0; 22 | return fldnode; 23 | } 24 | 25 | // Create a new field node that is a copy of an existing one 26 | INode *cloneFieldDclNode(CloneState *cstate, FieldDclNode *node) { 27 | FieldDclNode *newnode = memAllocBlk(sizeof(FieldDclNode)); 28 | memcpy(newnode, node, sizeof(FieldDclNode)); 29 | newnode->vtype = cloneNode(cstate, node->vtype); 30 | newnode->value = cloneNode(cstate, node->value); 31 | return (INode*)newnode; 32 | } 33 | 34 | // Serialize a field declaration node 35 | void fieldDclPrint(FieldDclNode *name) { 36 | inodePrintNode((INode*)name->perm); 37 | inodeFprint(" %s ", &name->namesym->namestr); 38 | inodePrintNode(name->vtype); 39 | if (name->value) { 40 | inodeFprint(" = "); 41 | if (name->value->tag == BlockTag) 42 | inodePrintNL(); 43 | inodePrintNode(name->value); 44 | } 45 | } 46 | 47 | // Enable name resolution of field declarations 48 | void fieldDclNameRes(NameResState *pstate, FieldDclNode *name) { 49 | inodeNameRes(pstate, (INode**)&name->perm); 50 | inodeNameRes(pstate, &name->vtype); 51 | 52 | if (name->value) 53 | inodeNameRes(pstate, &name->value); 54 | } 55 | 56 | // Type check field declaration against its initial value 57 | void fieldDclTypeCheck(TypeCheckState *pstate, FieldDclNode *name) { 58 | inodeTypeCheckAny(pstate, (INode**)&name->perm); 59 | if (itypeTypeCheck(pstate, &name->vtype) == 0) 60 | return; 61 | 62 | // An initializer need not be specified, but if not, it must have a declared type 63 | if (!name->value) { 64 | if (name->vtype == unknownType) { 65 | errorMsgNode((INode*)name, ErrorNoType, "Declared field must specify a type or value"); 66 | return; 67 | } 68 | } 69 | // Type check the initialization value 70 | else { 71 | // Fields require literal default values 72 | if (!litIsLiteral(name->value)) 73 | errorMsgNode(name->value, ErrorNotLit, "Field default must be a literal value."); 74 | // Otherwise, verify that declared type and initial value type matches 75 | else if (!iexpTypeCheckCoerce(pstate, name->vtype, &name->value)) 76 | errorMsgNode(name->value, ErrorInvType, "Initialization value's type does not match variable's declared type"); 77 | else if (name->vtype == unknownType) 78 | name->vtype = ((IExpNode *)name->value)->vtype; 79 | } 80 | 81 | // Fields cannot hold a void or opaque struct value 82 | if (!itypeIsConcrete(name->vtype)) 83 | errorMsgNode((INode*)name, ErrorInvType, "Field's type must be concrete and instantiable."); 84 | } 85 | -------------------------------------------------------------------------------- /src/c-compiler/ir/types/permission.c: -------------------------------------------------------------------------------- 1 | /** Permission Types 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #include "../ir.h" 9 | 10 | #include 11 | 12 | // Create a new permission declaration node 13 | PermNode *newPermDclNode(Name *namesym, uint16_t flags) { 14 | PermNode *node; 15 | newNode(node, PermNode, PermTag); 16 | node->namesym = namesym; 17 | node->llvmtype = NULL; 18 | iNsTypeInit((INsTypeNode*)node, 1); // May not need members for static types 19 | node->permflags = flags; 20 | return node; 21 | } 22 | 23 | // Create a new permission use node 24 | INode *newPermUseNode(PermNode *permdcl) { 25 | NameUseNode *perm; 26 | newNode(perm, NameUseNode, TypeNameUseTag); 27 | perm->vtype = NULL; 28 | perm->namesym = permdcl->namesym; 29 | perm->dclnode = (INode*)permdcl; 30 | perm->qualNames = NULL; 31 | return (INode*)perm; 32 | } 33 | 34 | // Serialize a permission node 35 | void permPrint(PermNode *node) { 36 | inodeFprint("%s ", &node->namesym->namestr); 37 | } 38 | 39 | // Get permission's flags 40 | int permGetFlags(INode *perm) { 41 | if (perm->tag == TypeNameUseTag) 42 | perm = (INode*)((NameUseNode*)perm)->dclnode; 43 | assert(perm->tag == PermTag); 44 | return ((PermNode *)perm)->permflags; 45 | } 46 | 47 | // Are the permissions the same? 48 | int permIsSame(INode *node1, INode *node2) { 49 | if (node1->tag == TypeNameUseTag) 50 | node1 = (INode*)((NameUseNode*)node1)->dclnode; 51 | if (node2->tag == TypeNameUseTag) 52 | node2 = (INode*)((NameUseNode*)node2)->dclnode; 53 | assert(node1->tag == PermTag && node2->tag == PermTag); 54 | return node1 == node2; 55 | } 56 | 57 | // Will 'from' permission coerce to the target? 58 | int permMatches(INode *ito, INode *ifrom) { 59 | PermNode *from = (PermNode *)((ifrom->tag == TypeNameUseTag)? (INode*)((NameUseNode*)ifrom)->dclnode : ifrom); 60 | PermNode *to = (PermNode *)((ito->tag == TypeNameUseTag)? (INode*)((NameUseNode*)ito)->dclnode : ito); 61 | assert(from->tag == PermTag && to->tag == PermTag); 62 | if (to==from || to==opaqPerm) 63 | return EqMatch; 64 | if (from == uniPerm && 65 | (to == roPerm || to == mutPerm || to == immPerm || to == mut1Perm)) 66 | return EqMatch; 67 | if (to == roPerm && 68 | (from == mutPerm || from == immPerm || from == mut1Perm)) 69 | return EqMatch; 70 | return NoMatch; 71 | } 72 | 73 | // Verify that permission init is correctly declared 74 | void permInitTypeCheck(INode *perm) { 75 | if (perm->tag != StructTag) 76 | return; 77 | 78 | FnDclNode *initmeth = (FnDclNode*)iTypeFindFnField(perm, initMethodName); 79 | if (initmeth == NULL) { 80 | return; 81 | } 82 | FnSigNode *initsig = (FnSigNode*)itypeGetTypeDcl(initmeth->vtype); 83 | if (initsig->parms->used != 0) { 84 | errorMsgNode((INode*)initmeth, ErrorInvType, "Permission init method may not have parameters."); 85 | return; 86 | } 87 | INode *initrettype = itypeGetTypeDcl(initsig->rettype); 88 | if (itypeMatches(initrettype, perm, Coercion) != EqMatch) { 89 | errorMsgNode((INode*)initmeth, ErrorInvType, "Permission init method must return initial value."); 90 | return; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /PLAN.md: -------------------------------------------------------------------------------- 1 | # Cone - Next Steps (as of June 1, 2022) 2 | 3 | ## Current Capability 4 | 5 | The Cone compiler supports an ever-growing set of language features. 6 | Enough that it is now possible to write programs that render 3D objects 7 | as OpenGL-based native executables 8 | or [WebGL-based WebAssembly modules](http://cone.jondgoodwin.com/example/index.html). 9 | 10 | At this point, Cone's implemented features are largely richer than C's core features (although there are still gaps). 11 | There are several ways to find out what it does, and does not, support: 12 | 13 | - The "Feature Status" section below gives a high-level view of which features are working or not. 14 | - A more detailed understanding can be gleaned from the robust language reference documentation. 15 | Each page describes both current and planned features in detail. 16 | At the top of each page is a summary of which features have not yet been implemented. 17 | - The [Cone Playground](http://cone.jondgoodwin.com/play/index.html) 18 | examples demonstrate many of the language's currently supported features. 19 | 20 | ## Current Focus: Modules, Packages and Libraries 21 | 22 | The language is becoming progressively more solid. As more features come online, bugs get squashed, and 23 | the design improves for versatility and ease-of-use, it becomes attractive to write larger 24 | and more interesting programs. As these programs grow bigger, so grows the need for packaging reusable 25 | module and type functionality into libraries. 26 | 27 | To make this easier: 28 | 29 | - For imported modules, do not generate implementation values/code, but still generate public names 30 | - Improve name mangling for modules, types, generic and overloaded functions 31 | - Improve the congo build tool to build the standard and other libraries, and then link them in to executable programs 32 | - Implement full name folding behavior for modules, including special-case handling for core library and single-type modules 33 | - Add some module capabilities to types (e.g., include, macro methods, typedef, subtypes) 34 | 35 | ## Feature Status 36 | 37 | This table illustrates the current status of Cone's key features: 38 | 39 | | Feature | Implemented | Planned | 40 | | --- | --- | --- | 41 | | **Control Flow** | Functions | closures | 42 | | | Methods for types | Constructors, finalizers, set methods | 43 | | | Return (+implicit) | | 44 | | | do, with blocks. 'this' operators | build blocks | 45 | | | if & block (expressions) match | partial pattern match | 46 | | | while, break, continue | each | 47 | | **Names** | Global, local, extern variables | | 48 | | | Module & type namespaces | | 49 | | | include, import | | 50 | | **Operators** | +, -, *, /, % | | 51 | | | == < <= > >= | ~~ | 52 | | | = : << | | 53 | | | ++, --, +=, *=, etc. | | 54 | | | . () [] * & | | 55 | | | & \| ^ ~ | | 56 | | | and, or, not/! | | 57 | | **Types** | u8, u16, u32, u64, i8, i16, i32, i64 | | 58 | | | f32, f64 | | 59 | | | Bool: true, false | | 60 | | | struct, traits, and tuples | inheritance | 61 | | | array, array refs | slices, collections | 62 | | | union & trait variant types | | 63 | | | references (incl. nullable) | safety guards | 64 | | | so, rc, borrowed | move/borrow semantics | 65 | | | | gc, arena, pool | 66 | | | static permissions | runtime permissions | 67 | | | pointers | trust block | 68 | | **Polymorphism** | | | 69 | | | Generics | | 70 | | | Macros | CTE | 71 | -------------------------------------------------------------------------------- /src/c-compiler/parser/parser.h: -------------------------------------------------------------------------------- 1 | /** Parser 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #ifndef parser_h 9 | #define parser_h 10 | 11 | #include "../ir/ir.h" 12 | typedef struct ConeOptions ConeOptions; 13 | 14 | typedef struct ParseState { 15 | ProgramNode *pgm; // Program node 16 | ModuleNode *pgmmod; // Root module for program 17 | ModuleNode *mod; // Current module 18 | INsTypeNode *typenode; // Current type 19 | char *gennamePrefix; // Module or type prefix for unique linker names 20 | } ParseState; 21 | 22 | // When parsing a variable definition, what syntax is allowed? 23 | enum ParseFlags { 24 | ParseMayName = 0x8000, // The variable may be named 25 | ParseMayAnon = 0x4000, // The variable may be anonymous 26 | ParseMaySig = 0x2000, // The variable may be signature only 27 | ParseMayImpl = 0x1000, // The variable may implement a code block 28 | ParseEmbedded = 0x0800, // Is embedded in expression (no semi) 29 | ParseMayConst = 0x0400 // const allowed for variable declaration 30 | }; 31 | 32 | // parsemod.c 33 | ProgramNode *parsePgm(ConeOptions *opt); 34 | ModuleNode *parseModuleBlk(ParseState *parse, ModuleNode *mod); 35 | 36 | // parsefnflow.c 37 | INode *parseFn(ParseState *parse, uint16_t mayflags); 38 | // Parse a macro declaration 39 | MacroDclNode *parseMacro(ParseState *parse); 40 | // Parse a list of generic variables and add to the genericnode 41 | Nodes *parseGenericParms(ParseState *parse); 42 | INode *parseIf(ParseState *parse); 43 | INode *parseMatch(ParseState *parse); 44 | INode *parseWhile(ParseState *parse, Name *lifesym, int stmtflag); 45 | // Parse an expression block 46 | INode *parseExprBlock(ParseState *parse, int isloop); 47 | INode *parseLifetime(ParseState *parse, int stmtflag); 48 | 49 | // parseexpr.c 50 | INode *parseSimpleExpr(ParseState *parse); 51 | INode *parseAnyExpr(ParseState *parse); 52 | // Parse a name use, which may be qualified with module names 53 | INode *parseNameUse(ParseState *parse); 54 | // Parse a term: literal, identifier, etc. 55 | INode *parseTerm(ParseState *parse); 56 | // Parse a prefix operator 57 | INode *parsePrefix(ParseState *parse, int noSuffix); 58 | 59 | // parsetype.c 60 | INode *parsePerm(); 61 | VarDclNode *parseVarDcl(ParseState *parse, PermNode *defperm, uint16_t flags); 62 | ConstDclNode *parseConstDcl(ParseState *parse); 63 | INode *parseFnSig(ParseState *parse); 64 | INode *parseStruct(ParseState *parse, uint16_t flags); 65 | INode *parseType(ParseState *parse); 66 | TypedefNode *parseTypedef(ParseState *parse); 67 | 68 | // parsehelper.c for statement/block start/end processing 69 | // Skip to next statement for error recovery 70 | void parseSkipToNextStmt(); 71 | // Is this end-of-statement? if ';', '}', or end-of-file 72 | int parseIsEndOfStatement(); 73 | // We expect optional semicolon since statement has run its course 74 | void parseEndOfStatement(); 75 | // Return true on '{' or ':' 76 | int parseHasBlock(); 77 | // Expect a block to start, consume its token and set lexer mode 78 | void parseBlockStart(); 79 | // Are we at end of block yet? If so, consume token and reset lexer mode 80 | int parseBlockEnd(); 81 | // Expect closing token (e.g., right parenthesis). If not found, search for it or '}' or ';' 82 | void parseCloseTok(uint16_t closetok); 83 | 84 | #endif 85 | -------------------------------------------------------------------------------- /src/c-compiler/ir/name.h: -------------------------------------------------------------------------------- 1 | /** Name handling - general purpose 2 | * 3 | * @file 4 | * 5 | * This source file is part of the Cone Programming Language C compiler 6 | * See Copyright Notice in conec.h 7 | */ 8 | 9 | #ifndef name_h 10 | #define name_h 11 | 12 | #include 13 | 14 | // Name is an interned symbol, unique by its collection of characters (<=255) 15 | // A name can be hashed into the global name table or a particular node's namespace. 16 | // The struct for a name is an unmovable allocated block in memory 17 | typedef struct Name { 18 | INode *node; // Node currently assigned to name 19 | size_t hash; // Name's computed hash 20 | unsigned char namesz; // Number of characters in the name (<=255) 21 | char namestr; // First byte of name's string (the rest follows) 22 | } Name; 23 | 24 | // Common symbols - see nametbl.c 25 | extern Name *anonName; // "_" - the absence of a name 26 | extern Name *tempName; // "-_" 27 | extern Name *selfName; // "self" 28 | extern Name *selfTypeName; // "Self" 29 | extern Name *thisName; // "this" 30 | extern Name *dropName; // "drop" 31 | extern Name *cloneName; // "clone" method 32 | extern Name *finalName; // "final" method 33 | 34 | extern Name *plusEqName; // "+=" 35 | extern Name *minusEqName; // "-=" 36 | extern Name *multEqName; // "*=" 37 | extern Name *divEqName; // "/=" 38 | extern Name *remEqName; // "%=" 39 | extern Name *orEqName; // "|=" 40 | extern Name *andEqName; // "&=" 41 | extern Name *xorEqName; // "^=" 42 | extern Name *shlEqName; // "<<=" 43 | extern Name *shrEqName; // ">>=" 44 | extern Name *lessDashName; // "<-" 45 | 46 | extern Name *plusName; // "+" 47 | extern Name *minusName; // "-" 48 | extern Name *istrueName; // "isTrue" 49 | extern Name *multName; // "*" 50 | extern Name *divName; // "/" 51 | extern Name *remName; // "%" 52 | extern Name *orName; // "|" 53 | extern Name *andName; // "&" 54 | extern Name *xorName; // "^" 55 | extern Name *shlName; // "<<" 56 | extern Name *shrName; // ">>" 57 | 58 | extern Name *incrName; // "++" 59 | extern Name *decrName; // "--" 60 | extern Name *incrPostName; // "_++" 61 | extern Name *decrPostName; // "_--" 62 | 63 | extern Name *eqName; // "==" 64 | extern Name *neName; // "!=" 65 | extern Name *leName; // "<=" 66 | extern Name *ltName; // "<" 67 | extern Name *geName; // ">=" 68 | extern Name *gtName; // ">" 69 | 70 | extern Name *parensName; // "()" 71 | extern Name *indexName; // "[]" 72 | extern Name *refIndexName; // "&[]" 73 | 74 | extern Name *corelibName; // "corelib" 75 | extern Name *optionName; // "Option" 76 | 77 | extern Name *rcName; // "rc" 78 | extern Name *soName; // "so" 79 | extern Name *allocMethodName; // "_alloc" 80 | extern Name *initMethodName; // "init" 81 | 82 | typedef struct VarDclNode VarDclNode; 83 | typedef struct FnDclNode FnDclNode; 84 | 85 | // Create new prefix that concatenates a new name to _ 86 | void nameNewPrefix(char **prefix, char *name); 87 | // Create new prefix that concatenates a new name to the old prefix, followed by _ 88 | void nameConcatPrefix(char **prefix, char *name); 89 | // Create globally unique variable name, prefixed by module/type name 90 | void nameGenVarName(VarDclNode *node, char *prefix); 91 | // Create globally unique mangled function name, prefixed by module/type name 92 | void nameGenFnName(FnDclNode *node, char *prefix); 93 | 94 | 95 | #endif 96 | -------------------------------------------------------------------------------- /src/c-compiler/shared/error.c: -------------------------------------------------------------------------------- 1 | /** Error Handling 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #include "error.h" 9 | #include "timer.h" 10 | #include "../parser/lexer.h" 11 | #include "../ir/ir.h" 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | int errors = 0; 18 | int warnings = 0; 19 | 20 | // Send an error message to stderr 21 | void errorExit(int exitcode, const char *msg, ...) { 22 | // Do a formatted output, passing along all args 23 | va_list argptr; 24 | va_start(argptr, msg); 25 | vfprintf(stderr, msg, argptr); 26 | va_end(argptr); 27 | fputs("\n", stderr); 28 | 29 | // Exit with return code 30 | #ifdef _DEBUG 31 | getchar(); // Hack for VS debugging 32 | #endif 33 | exit(exitcode); 34 | } 35 | 36 | // Send an error message to stderr 37 | void errorOut(int code, const char *msg, va_list args) { 38 | // Prefix for error message 39 | if (code < WarnCode) { 40 | errors++; 41 | fprintf(stderr, "Error %d: ", code); 42 | } 43 | else if (code < Uncounted) { 44 | warnings++; 45 | fprintf(stderr, "Warning %d: ", code); 46 | } 47 | 48 | // Do a formatted output of message, passing along all args 49 | vfprintf(stderr, msg, args); 50 | fputs("\n", stderr); 51 | } 52 | 53 | // Send an error message plus code context to stderr 54 | void errorOutCode(char *tokp, uint32_t linenbr, char *linep, char *url, int code, const char *msg, va_list args) { 55 | char *srcp; 56 | int pos, spaces; 57 | 58 | // Send out the error message and count 59 | errorOut(code, msg, args); 60 | 61 | // Reflect the source code line 62 | fputs(" --> ", stderr); 63 | srcp = linep; 64 | while (*srcp && *srcp!='\n') 65 | fputc(*srcp++, stderr); 66 | fputc('\n', stderr); 67 | 68 | // Depict where error message applies along with source file/pos info 69 | fprintf(stderr, " "); 70 | pos = (spaces = tokp - linep) + 1; 71 | srcp = linep; 72 | while (spaces--) { 73 | fputc(*srcp++ == '\t'? '\t' : ' ', stderr); 74 | } 75 | fprintf(stderr, "^--- %s:%d:%d\n", url, linenbr, pos); 76 | } 77 | 78 | // Send an error message to stderr 79 | void errorMsgNode(INode *node, int code, const char *msg, ...) { 80 | va_list argptr; 81 | va_start(argptr, msg); 82 | errorOutCode(node->srcp, node->linenbr, node->linep, node->lexer->url, code, msg, argptr); 83 | va_end(argptr); 84 | if (node->instnode) 85 | errorMsgNode(node->instnode, Uncounted, "... as instantiated by this part of the source code"); 86 | } 87 | 88 | // Send an error message to stderr 89 | void errorMsgLex(int code, const char *msg, ...) { 90 | va_list argptr; 91 | va_start(argptr, msg); 92 | errorOutCode(lex->tokp, lex->linenbr, lex->linep, lex->url, code, msg, argptr); 93 | va_end(argptr); 94 | } 95 | 96 | // Send an error message to stderr 97 | void errorMsg(int code, const char *msg, ...) { 98 | va_list argptr; 99 | va_start(argptr, msg); 100 | errorOut(code, msg, argptr); 101 | va_end(argptr); 102 | } 103 | 104 | // Generate final message for a compile 105 | void errorSummary() { 106 | if (errors > 0) 107 | errorExit(ExitError, "Unsuccessful compile: %d errors, %d warnings", errors, warnings); 108 | fprintf(stderr, "Compile finished in %.6g sec (%lu kb). %d warnings detected\n", timerSummary(), memUsed()/1024, warnings); 109 | } 110 | -------------------------------------------------------------------------------- /src/c-compiler/ir/exp/allocate.c: -------------------------------------------------------------------------------- 1 | /** Handling for allocate expression nodes 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #include "../ir.h" 9 | 10 | #include 11 | 12 | // Serialize allocate 13 | void allocatePrint(RefNode *node) { 14 | inodeFprint("+("); 15 | inodePrintNode(node->vtype); 16 | inodeFprint("->"); 17 | inodePrintNode(node->vtexp); 18 | inodeFprint(")"); 19 | } 20 | 21 | // Name resolution for questag: decide if Option type or fold into AllocNode 22 | void allocateQuesNameRes(NameResState *pstate, FnCallNode **nodep) { 23 | FnCallNode *quesNode = *nodep; 24 | 25 | inodeNameRes(pstate, &quesNode->objfn); 26 | inodeNameRes(pstate, &nodesGet(quesNode->args, 0)); 27 | 28 | quesNode->tag = FnCallTag; // Treat as option type 29 | INode *argnode = nodesGet(quesNode->args, 0); 30 | if (isTypeNode(argnode)) { 31 | // When arg is a type, then treat this as Option[T] type 32 | } 33 | else if (argnode->tag == AllocateTag) { 34 | RefNode *allocnode = (RefNode*)argnode; 35 | allocnode->flags |= FlagQues; 36 | allocnode->vtype = (INode*)quesNode; // in TypeCheck, this will be updated 37 | *((INode**)nodep) = argnode; 38 | } 39 | else { 40 | errorMsgNode((INode*)quesNode, ErrorInvType, "'?' is not valid here."); 41 | } 42 | } 43 | 44 | // Type check allocate node 45 | void allocateTypeCheck(TypeCheckState *pstate, RefNode **nodep) { 46 | RefNode *node = *nodep; 47 | 48 | // The default permission type is 'uni' 49 | if (node->perm == unknownType) 50 | node->perm = newPermUseNode(uniPerm); 51 | 52 | // Ensure expression is a value usable for initializing allocated memory 53 | if (node->tag == ArrayAllocTag && node->vtexp->tag == ArrayLitTag) 54 | // Somewhat different Array literal type check that allows expression for array dimension 55 | arrayLitTypeCheckDimExp(pstate, (ArrayNode *)node->vtexp); 56 | else if (iexpTypeCheckAny(pstate, &node->vtexp) == 0) 57 | return; 58 | 59 | INode *vtype = ((IExpNode*)node->vtexp)->vtype; 60 | if (!itypeIsConcrete(vtype) || itypeIsZeroSize(vtype)) { 61 | errorMsgNode(node->vtexp, ErrorInvType, "May not allocate a value of abstract or zero-size type"); 62 | } 63 | if (node->tag == ArrayAllocTag) { 64 | if (vtype->tag == ArrayTag) 65 | vtype = nodesGet(((ArrayNode *)vtype)->elems, 0); 66 | else 67 | errorMsgNode(node->vtexp, ErrorInvType, "Invalid type for array reference's initial value"); 68 | } 69 | 70 | // Infer reference's value type based on initial value 71 | RefNode *reftype = newRefNodeFull(node->tag==ArrayAllocTag? ArrayRefTag : RefTag, 72 | (INode*)node, node->region, node->perm, vtype); 73 | if (node->flags & FlagQues) { 74 | // node->vtype already has an Option node (as FnCall). Fix up its parametric type 75 | FnCallNode *option = (FnCallNode *)node->vtype; 76 | INode **parm = &nodesGet(option->args, 0); 77 | *parm = (INode*)reftype; 78 | } 79 | else 80 | node->vtype = (INode *)reftype; 81 | inodeTypeCheckAny(pstate, &node->vtype); 82 | 83 | // Type check that ref region + permission's allocation functions are declared correctly 84 | regionAllocTypeCheck(itypeGetTypeDcl(node->region)); 85 | permInitTypeCheck(itypeGetTypeDcl(node->perm)); 86 | } 87 | 88 | // Perform data flow analysis on allocate node 89 | void allocateFlow(FlowState *fstate, RefNode **nodep) { 90 | RefNode *node = *nodep; 91 | // For an allocated reference, we need to handle the copied value 92 | flowLoadValue(fstate, &node->vtexp); 93 | flowHandleMoveOrCopy(&node->vtexp); 94 | } 95 | -------------------------------------------------------------------------------- /src/c-compiler/ir/meta/macro.c: -------------------------------------------------------------------------------- 1 | /** Handling for gennode declaration nodes 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #include "../ir.h" 9 | 10 | #include 11 | #include 12 | 13 | // Create a new generic declaraction node 14 | MacroDclNode *newMacroDclNode(Name *namesym) { 15 | MacroDclNode *gennode; 16 | newNode(gennode, MacroDclNode, MacroDclTag); 17 | gennode->vtype = NULL; 18 | gennode->namesym = namesym; 19 | gennode->parms = newNodes(4); 20 | gennode->body = NULL; 21 | gennode->memonodes = newNodes(4); 22 | return gennode; 23 | } 24 | 25 | // Serialize 26 | void macroPrint(MacroDclNode *name) { 27 | INode **nodesp; 28 | uint32_t cnt; 29 | inodeFprint("macro %s (", &name->namesym->namestr); 30 | for (nodesFor(name->parms, cnt, nodesp)) { 31 | inodePrintNode(*nodesp); 32 | if (cnt > 1) 33 | inodeFprint(", "); 34 | } 35 | inodeFprint(") "); 36 | inodePrintNode(name->body); 37 | } 38 | 39 | // Perform name resolution 40 | void macroNameRes(NameResState *pstate, MacroDclNode *gennode) { 41 | uint16_t oldscope = pstate->scope; 42 | pstate->scope = 1; 43 | 44 | INode **nodesp; 45 | uint32_t cnt; 46 | for (nodesFor(gennode->parms, cnt, nodesp)) 47 | inodeNameRes(pstate, nodesp); 48 | 49 | // Hook gennode's parameters into global name table 50 | // so that when we walk the gennode's logic, parameter names are resolved 51 | nametblHookPush(); 52 | for (nodesFor(gennode->parms, cnt, nodesp)) 53 | nametblHookNode(((VarDclNode *)*nodesp)->namesym, *nodesp); 54 | 55 | inodeNameRes(pstate, (INode**)&gennode->body); 56 | 57 | nametblHookPop(); 58 | pstate->scope = oldscope; 59 | } 60 | 61 | // Type check a generic declaration 62 | void macroTypeCheck(TypeCheckState *pstate, MacroDclNode *gennode) { 63 | } 64 | 65 | // Type check generic name use 66 | void macroNameTypeCheck(TypeCheckState *pstate, NameUseNode **gennode) { 67 | // Obtain macro to expand 68 | MacroDclNode *macrodcl = (MacroDclNode*)(*gennode)->dclnode; 69 | uint32_t expected = macrodcl->parms ? macrodcl->parms->used : 0; 70 | if (expected > 0) { 71 | errorMsgNode((INode*)*gennode, ErrorManyArgs, "Generic or macro expects arguments to be provided"); 72 | return; 73 | } 74 | 75 | // Instantiate macro, replacing gennode 76 | CloneState cstate; 77 | clonePushState(&cstate, (INode*)*gennode, NULL, pstate->scope, NULL, NULL); 78 | *((INode**)gennode) = cloneNode(&cstate, macrodcl->body); 79 | clonePopState(); 80 | 81 | // Now type check the instantiated nodes 82 | inodeTypeCheckAny(pstate, (INode**)gennode); 83 | } 84 | 85 | // Instantiate a generic using passed arguments 86 | void macroCallTypeCheck(TypeCheckState *pstate, FnCallNode **nodep) { 87 | MacroDclNode *genericnode = (MacroDclNode*)((NameUseNode*)(*nodep)->objfn)->dclnode; 88 | 89 | uint32_t expected = genericnode->parms ? genericnode->parms->used : 0; 90 | if ((*nodep)->args->used != expected) { 91 | errorMsgNode((INode*)*nodep, ErrorManyArgs, "Incorrect number of arguments vs. parameters expected"); 92 | return; 93 | } 94 | 95 | // Replace gennode call with instantiated body, substituting parameters 96 | CloneState cstate; 97 | clonePushState(&cstate, (INode*)*nodep, NULL, pstate->scope, genericnode->parms, (*nodep)->args); 98 | *((INode**)nodep) = cloneNode(&cstate, genericnode->body); 99 | clonePopState(); 100 | 101 | // Now type check the instantiated nodes 102 | inodeTypeCheckAny(pstate, (INode **)nodep); 103 | } 104 | 105 | -------------------------------------------------------------------------------- /src/c-compiler/genllvm/genllvm.h: -------------------------------------------------------------------------------- 1 | /** Generator for LLVM 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #ifndef genllvm_h 9 | #define genllvm_h 10 | 11 | #include "../ir/ir.h" 12 | #include "../coneopts.h" 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | // An entry for each active loop block in current control flow stack 19 | #define GenBlockStackMax 256 20 | typedef struct { 21 | BlockNode *blocknode; 22 | LLVMBasicBlockRef blockbeg; 23 | LLVMBasicBlockRef blockend; 24 | LLVMValueRef *phis; 25 | LLVMBasicBlockRef *blocksFrom; 26 | uint32_t phiCnt; 27 | } GenBlockState; 28 | 29 | typedef struct GenState { 30 | LLVMTargetMachineRef machine; 31 | LLVMTargetDataRef datalayout; 32 | LLVMContextRef context; 33 | LLVMModuleRef module; 34 | LLVMValueRef fn; 35 | LLVMValueRef allocaPoint; 36 | LLVMBuilderRef builder; 37 | LLVMBasicBlockRef block; 38 | 39 | LLVMDIBuilderRef dibuilder; 40 | LLVMMetadataRef compileUnit; 41 | LLVMMetadataRef difile; 42 | 43 | LLVMTypeRef emptyStructType; 44 | 45 | ConeOptions *opt; 46 | INode *fnblock; 47 | GenBlockState *blockstack; 48 | uint32_t blockstackcnt; 49 | } GenState; 50 | 51 | // Different kinds of dispatch 52 | enum FnCallDispatch { 53 | SimpleDispatch, // Call function directly or indirectly 54 | VirtDispatch // Lookup function in vtable, and then dispatch 55 | }; 56 | 57 | // Setup LLVM generation, ensuring we know intended target 58 | void genSetup(GenState *gen, ConeOptions *opt); 59 | void genClose(GenState *gen); 60 | void genpgm(GenState *gen, ProgramNode *pgm); 61 | void genlFn(GenState *gen, FnDclNode *fnnode); 62 | void genlGloVarName(GenState *gen, VarDclNode *glovar); 63 | void genlGloFnName(GenState *gen, FnDclNode *glofn); 64 | 65 | // genlstmt.c 66 | LLVMBasicBlockRef genlInsertBlock(GenState *gen, char *name); 67 | LLVMValueRef genlBlock(GenState *gen, BlockNode *blk); 68 | 69 | // genlexpr.c 70 | LLVMValueRef genlExpr(GenState *gen, INode *termnode); 71 | // Generate a function call, including special intrinsics (Internal version) 72 | LLVMValueRef genlFnCallInternal(GenState *gen, int dispatch, INode *objfn, uint32_t fnargcnt, LLVMValueRef *fnargs); 73 | // Generate a panic 74 | void genlPanic(GenState *gen); 75 | 76 | // genlalloc.c 77 | // Build usable metadata about a reference 78 | void genlRefTypeSetup(GenState *gen, RefNode *reftype); 79 | // Generate code that creates an allocated ref by allocating and initializing 80 | LLVMValueRef genlallocref(GenState *gen, RefNode *allocatenode); 81 | // Progressively dealias or drop all declared variables in nodes list 82 | void genlDealiasNodes(GenState *gen, Nodes *nodes); 83 | // Add to the counter of an rc allocated reference 84 | void genlRcCounter(GenState *gen, LLVMValueRef ref, long long amount, RefNode *refnode); 85 | // Dealias an own allocated reference 86 | void genlDealiasOwn(GenState *gen, LLVMValueRef ref, RefNode *refnode); 87 | // Create an alloca (will be pushed to the entry point of the function. 88 | LLVMValueRef genlAlloca(GenState *gen, LLVMTypeRef type, const char *name); 89 | 90 | // genltype.c 91 | // Generate a type value 92 | LLVMTypeRef genlType(GenState *gen, INode *typ); 93 | // Generate LLVM value corresponding to the size of a type 94 | LLVMValueRef genlSizeof(GenState *gen, INode *vtype); 95 | // Generate unsigned integer whose bits are same size as a pointer 96 | LLVMTypeRef genlUsize(GenState *gen); 97 | LLVMTypeRef genlEmptyStruct(GenState* gen); 98 | // Generate a vtable type 99 | void genlVtable(GenState *gen, Vtable *vtable); 100 | 101 | #endif 102 | -------------------------------------------------------------------------------- /src/c-compiler/ir/types/struct.h: -------------------------------------------------------------------------------- 1 | /** Handling for record-based types with fields 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #ifndef struct_h 9 | #define struct_h 10 | 11 | typedef struct ModuleNode ModuleNode; 12 | 13 | // Describes how some struct implements a virtual reference's vtable 14 | typedef struct { 15 | INode *structdcl; // struct that implements 16 | Nodes *methfld; // specific methods and fields in same order as vtable 17 | char *name; // generated name for the implemented vtable 18 | LLVMValueRef llvmvtablep; // generates a pointer to the implemented vtable 19 | } VtableImpl; 20 | 21 | // Describes the virtual interface supported by some trait/struct 22 | typedef struct { 23 | Nodes *methfld; // list of public methods and then fields 24 | Nodes *impl; // list of VtableImpl, for structs using this virtref 25 | char *name; // generated name for the vtable type 26 | LLVMTypeRef llvmvtable; // for the vtable 27 | LLVMTypeRef llvmreftype; // For the virtual reference, not the vtable 28 | LLVMValueRef llvmvtables; // List of vtables 29 | } Vtable; 30 | 31 | // Field-containing types (e.g., struct, trait, etc.) 32 | // - fields holds all owned and trait-inherited fields 33 | // - nodelist holds owned methods and static functions and variables 34 | // - namespace is the dictionary of all owned and inherited named nodes 35 | typedef struct StructNode { 36 | INsTypeNodeHdr; 37 | Name *namesym; 38 | ModuleNode *mod; // Owning module, to check if struct defined in same mod as trait 39 | INode *basetrait; // Which trait has fields embedded at start of this trait/struct 40 | Nodes *derived; // If a closed, base trait, this lists all structs derived from it 41 | NodeList fields; // Ordered list of all fields 42 | Vtable *vtable; // Pointer to vtable info (may be NULL) 43 | GenericInfo *genericinfo; // Link to generic parms, etc (or NULL if not generic) 44 | uint32_t tagnbr; // If a tagged struct, this is the number in the tag field 45 | } StructNode; 46 | 47 | typedef struct FieldDclNode FieldDclNode; 48 | 49 | StructNode *newStructNode(Name *namesym); 50 | 51 | // Clone struct 52 | INode *cloneStructNode(CloneState *cstate, StructNode *node); 53 | 54 | // Add a field node to a struct type 55 | void structAddField(StructNode *type, FieldDclNode *node); 56 | 57 | void structPrint(StructNode *node); 58 | 59 | // Name resolution of a struct type 60 | void structNameRes(NameResState *pstate, StructNode *node); 61 | 62 | // Get bottom-most base trait for some trait/struct, or NULL if there is not one 63 | StructNode *structGetBaseTrait(StructNode *node); 64 | 65 | // Type check a struct type 66 | void structTypeCheck(TypeCheckState *pstate, StructNode *name); 67 | 68 | // Populate the vtable for this struct 69 | void structMakeVtable(StructNode *node); 70 | 71 | // Populate the vtable implementation info for a struct ref being coerced to some trait 72 | TypeCompare structVirtRefMatches(StructNode *trait, StructNode *strnode); 73 | 74 | // Will from-type coerce to to-struct (we know they are not the same) 75 | // We can only do this for a same-sized trait supertype 76 | TypeCompare structMatches(StructNode *to, INode *fromdcl, SubtypeConstraint constraint); 77 | 78 | // Return a type that is the supertype of both type nodes, or NULL if none found 79 | INode *structFindSuper(INode *type1, INode *type2); 80 | 81 | // Return a type that is the supertype of both type nodes, or NULL if none found 82 | // This is used by reference types, where same-sized is no longer a requirement 83 | INode *structRefFindSuper(INode *type1, INode *type2); 84 | 85 | #endif 86 | -------------------------------------------------------------------------------- /src/c-compiler/conec.c: -------------------------------------------------------------------------------- 1 | /** Main program file 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #include "conec.h" 9 | #include "coneopts.h" 10 | #include "shared/fileio.h" 11 | #include "ir/nametbl.h" 12 | #include "ir/ir.h" 13 | #include "shared/error.h" 14 | #include "shared/timer.h" 15 | #include "parser/lexer.h" 16 | #include "parser/parser.h" 17 | #include "genllvm/genllvm.h" 18 | 19 | #include 20 | #include 21 | 22 | // Run all semantic analysis passes against the AST/IR (after parse and before gen) 23 | void doAnalysis(ProgramNode **pgm) { 24 | 25 | // Resolve all name uses to their appropriate declaration 26 | // Note: Some nodes may be replaced (e.g., 'a' to 'self.a') 27 | NameResState nstate; 28 | nstate.mod = NULL; 29 | nstate.typenode = NULL; 30 | nstate.loopblock = NULL; 31 | nstate.scope = 0; 32 | nstate.flags = 0; 33 | inodeNameRes(&nstate, (INode**)pgm); 34 | if (errors) 35 | return; 36 | 37 | // Apply syntactic sugar, and perform type inference/check: 38 | // 1. Modules will do all its variables/function sigs first, before values/bodies 39 | // 2. Type checking pass will first substitute macros/generics 40 | // 3. A node will first type check all its subnodes, before checking types and other rules 41 | // 4. Type checking and inference are performed bidirectionally, expecting agreement 42 | // 5. When a function body has been type checked, data flow analysis is then performed on it 43 | // Note: Some nodes may be lowered, injected or replaced (particularly fncall) 44 | // 45 | // Type checking of type nodes will go depth first (recursively) from a nameuse reference to the type's dcl 46 | // in order to infectiously fill in information about these types: 47 | // - A type may not be composed of a zero - size type 48 | // - Pointers allow for recursive types, but otherwise, types must form a directed acyclic graph 49 | // - Infectiousness of types is handled (move semantics, lifetimes, thread-bound, etc.) 50 | // - Subtype and inheritance relationships are filled out 51 | // - The binary encoding is sorted (e.g., ensuring variant types are same size) 52 | TypeCheckState tstate; 53 | tstate.fn = NULL; 54 | tstate.typenode = NULL; 55 | inodeTypeCheckAny(&tstate, (INode**)pgm); 56 | } 57 | 58 | int main(int argc, char **argv) { 59 | ConeOptions coneopt; 60 | GenState gen; 61 | int ok; 62 | 63 | // Get compiler's options from passed arguments 64 | ok = coneOptSet(&coneopt, &argc, argv); 65 | if (ok <= 0) 66 | exit(ok == 0 ? 0 : ExitOpts); 67 | if (argc < 2) 68 | errorExit(ExitOpts, "Specify a Cone program to compile."); 69 | coneopt.srcpath = argv[1]; 70 | coneopt.srcname = fileName(coneopt.srcpath); 71 | 72 | // We set up generation early because we need target info, e.g.: pointer size 73 | timerBegin(SetupTimer); 74 | genSetup(&gen, &coneopt); 75 | 76 | // Parse source file, do semantic analysis, and generate code 77 | timerBegin(ParseTimer); 78 | ProgramNode* pgmnode = parsePgm(&coneopt); 79 | if (errors == 0) { 80 | timerBegin(SemTimer); 81 | doAnalysis(&pgmnode); 82 | if (errors == 0) { 83 | timerBegin(GenTimer); 84 | if (coneopt.print_ir) 85 | inodePrint(coneopt.output, coneopt.srcpath, (INode*)pgmnode); 86 | genpgm(&gen, pgmnode); 87 | genClose(&gen); 88 | } 89 | } 90 | timerBegin(TimerCount); 91 | 92 | // Close up everything necessary 93 | if (coneopt.verbosity > 0) 94 | timerPrint(); 95 | errorSummary(); 96 | #ifdef _DEBUG 97 | getchar(); // Hack for VS debugging 98 | #endif 99 | } 100 | -------------------------------------------------------------------------------- /src/c-compiler/ir/instype.c: -------------------------------------------------------------------------------- 1 | /** Shared logic for namespace-based types 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #include "ir.h" 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | // Initialize common fields 15 | void iNsTypeInit(INsTypeNode *type, int nodecnt) { 16 | nodelistInit(&type->nodelist, nodecnt); 17 | namespaceInit(&type->namespace, nodecnt); 18 | type->dropfn = NULL; 19 | // type->subtypes = newNodes(0); 20 | } 21 | 22 | // Add a function or potentially overloaded method to dictionary 23 | // If method is overloaded, add it to the link chain of same named methods 24 | void iNsTypeAddFnDict(INsTypeNode *type, FnDclNode *fnnode) { 25 | FnDclNode *foundnode = (FnDclNode*)namespaceAdd(&type->namespace, fnnode->namesym, (INode*)fnnode); 26 | if (foundnode) { 27 | if (foundnode->tag != FnDclTag 28 | || !(foundnode->flags & FlagMethFld) || !(fnnode->flags & FlagMethFld)) { 29 | errorMsgNode((INode*)fnnode, ErrorDupName, "Duplicate name %s: Only methods can be overloaded.", &fnnode->namesym->namestr); 30 | return; 31 | } 32 | // Append to end of linked method list 33 | while (foundnode->nextnode) 34 | foundnode = foundnode->nextnode; 35 | foundnode->nextnode = fnnode; 36 | } 37 | } 38 | 39 | // Add a function/method to type's dictionary and owned list 40 | void iNsTypeAddFn(INsTypeNode *type, FnDclNode *fnnode) { 41 | NodeList *mnodes = &type->nodelist; 42 | nodelistAdd(mnodes, (INode*)fnnode); 43 | iNsTypeAddFnDict(type, fnnode); 44 | } 45 | 46 | // Find the named node (could be method or field) 47 | // Return the node, if found or NULL if not found 48 | INode *iNsTypeFindFnField(INsTypeNode *type, Name *name) { 49 | return namespaceFind(&type->namespace, name); 50 | } 51 | 52 | // Find method that best fits the passed arguments 53 | FnDclNode *iNsTypeFindBestMethod(FnDclNode *firstmethod, INode **self, Nodes *args) { 54 | // Look for best-fit method 55 | FnDclNode *bestmethod = NULL; 56 | int bestnbr = 0x7fffffff; // ridiculously high number 57 | for (FnDclNode *methnode = (FnDclNode *)firstmethod; methnode; methnode = methnode->nextnode) { 58 | int match; 59 | switch (match = fnSigMatchMethCall((FnSigNode *)methnode->vtype, self, args)) { 60 | case 0: continue; // not an acceptable match 61 | case 1: return methnode; // perfect match! 62 | default: // imprecise match using conversions 63 | if (match < bestnbr) { 64 | // Remember this as best found so far 65 | bestnbr = match; 66 | bestmethod = methnode; 67 | } 68 | } 69 | } 70 | return bestmethod; 71 | } 72 | 73 | // Find method whose method signature matches exactly (except for self) 74 | FnDclNode *iNsTypeFindVrefMethod(FnDclNode *firstmeth, FnDclNode *matchmeth) { 75 | if (firstmeth == NULL || firstmeth->tag != FnDclTag) { 76 | //errorMsgNode(errnode, ErrorInvType, "%s cannot be coerced to a %s virtual reference. Missing method %s.", 77 | // &strnode->namesym->namestr, &trait->namesym->namestr, &meth->namesym->namestr); 78 | return 0; 79 | } 80 | // Look through all overloaded methods for a match 81 | while (firstmeth) { 82 | if (fnSigVrefEqual((FnSigNode*)firstmeth->vtype, (FnSigNode*)matchmeth->vtype)) 83 | break; 84 | firstmeth = firstmeth->nextnode; 85 | } 86 | if (firstmeth == NULL) { 87 | //errorMsgNode(errnode, ErrorInvType, "%s cannot be coerced to a %s virtual reference. Incompatible type for method %s.", 88 | // &strnode->namesym->namestr, &trait->namesym->namestr, &meth->namesym->namestr); 89 | return 0; 90 | } 91 | return firstmeth; 92 | } 93 | -------------------------------------------------------------------------------- /src/c-compiler/shared/memory.c: -------------------------------------------------------------------------------- 1 | /** Memory management 2 | * @file 3 | * 4 | * The compiler's memory management is deliberately leaky for high performance. 5 | * Allocation is done via bump pointer within very large arenas allocated from the heap 6 | * Nothing is ever freed. 7 | * 8 | * This source file is part of the Cone Programming Language C compiler 9 | * See Copyright Notice in conec.h 10 | */ 11 | 12 | #include "memory.h" 13 | #include "error.h" 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | // Public globals: Arena size configuration values 21 | size_t gMemBlkArenaSize = 256 * 4096; 22 | size_t gMemStrArenaSize = 128 * 4096; 23 | 24 | // Private globals: memory allocation arena bookkeeping 25 | static void *gMemBlkArenaPos = NULL; 26 | static size_t gMemBlkArenaLeft = 0; 27 | static void *gMemStrArenaPos = NULL; 28 | static size_t gMemStrArenaLeft = 0; 29 | 30 | static size_t memAllocated = 0; 31 | 32 | /** Allocate memory for a block, aligned to a 16-byte boundary */ 33 | void *memAllocBlk(size_t size) { 34 | void *memp; 35 | 36 | // Align to 16-byte boundary 37 | size = (size + 15) & ~15; 38 | 39 | // Return next bite out of arena, if it fits 40 | if (size <= gMemBlkArenaLeft) { 41 | gMemBlkArenaLeft -= size; 42 | memp = gMemBlkArenaPos; 43 | gMemBlkArenaPos = (char*)gMemBlkArenaPos + size; 44 | return memp; 45 | } 46 | 47 | // Return a newly allocated area, if bigger than arena can hold 48 | if (size > gMemBlkArenaSize) { 49 | memp = malloc(size); 50 | memAllocated += size; 51 | if (memp==NULL) 52 | errorExit(ExitMem, "Error: Out of memory"); 53 | return memp; 54 | } 55 | 56 | // Allocate a new Arena and return next bite out of it 57 | gMemBlkArenaPos = malloc(gMemBlkArenaSize); 58 | memAllocated += gMemBlkArenaSize; 59 | if (gMemBlkArenaPos==NULL) 60 | errorExit(ExitMem, "Error: Out of memory"); 61 | gMemBlkArenaLeft = gMemBlkArenaSize - size; 62 | memp = gMemBlkArenaPos; 63 | gMemBlkArenaPos = (char*)gMemBlkArenaPos + size; 64 | return memp; 65 | } 66 | 67 | /** Allocate memory for a string and copy contents over, if not NULL 68 | * Allocates extra byte for string-ending 0, appending it to copied string */ 69 | char *memAllocStr(char *str, size_t size) { 70 | void *strp; 71 | 72 | // Give it room for C-string null terminator 73 | size += 1; 74 | 75 | // Return next bite out of arena, if it fits 76 | if (size <= gMemStrArenaLeft) { 77 | gMemStrArenaLeft -= size; 78 | strp = gMemStrArenaPos; 79 | gMemStrArenaPos = (char*)gMemStrArenaPos + size; 80 | } 81 | 82 | // Return a newly allocated area, if bigger than arena can hold 83 | else if (size > gMemStrArenaSize) { 84 | strp = malloc(size); 85 | memAllocated += size; 86 | if (strp==NULL) 87 | errorExit(ExitMem, "Error: Out of memory"); 88 | } 89 | 90 | // Allocate a new Arena and return next bite out of it 91 | else { 92 | gMemStrArenaPos = malloc(gMemStrArenaSize); 93 | memAllocated += gMemStrArenaSize; 94 | if (gMemStrArenaPos==NULL) 95 | errorExit(ExitMem, "Error: Out of memory"); 96 | gMemStrArenaLeft = gMemStrArenaSize - size; 97 | strp = gMemStrArenaPos; 98 | gMemStrArenaPos = (char*)gMemStrArenaPos + size; 99 | } 100 | 101 | // Copy string contents into it 102 | if (str) { 103 | strncpy((char*)strp, str, --size); 104 | *((char*)strp+size) = '\0'; 105 | } 106 | return (char*) strp; 107 | } 108 | 109 | size_t nametblUnused(); 110 | // Return how much memory actually needed for use 111 | size_t memUsed() { 112 | return memAllocated - gMemBlkArenaLeft - gMemStrArenaLeft - nametblUnused(); 113 | } 114 | -------------------------------------------------------------------------------- /src/c-compiler/ir/itype.h: -------------------------------------------------------------------------------- 1 | /** Generic Type node handling 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #ifndef itype_h 9 | #define itype_h 10 | 11 | // Result from comparing subtype relationship between two types 12 | typedef enum { 13 | NoMatch, // Types are incompatible 14 | EqMatch, // Types are the same (equivalent) 15 | CastSubtype, // Subtype: From type can be recast to 'to' type (compile-time upcast) 16 | ConvSubtype, // Subtype: From type can be converted to 'to' type (runtime upcast) 17 | ConvByMeth, // Convert by using a method 18 | ConvBorrow, // Convert by auto-borrowing 19 | } TypeCompare; 20 | 21 | // The constraint context for comparing a subtyping relationship 22 | // This determines the severity of extra constraints, 23 | // due to the absence of some coercion conversions 24 | typedef enum { 25 | Monomorph, // Monomorphization - no constraints 26 | Virtref, // Virtual reference - relaxed 27 | Regref, // Regular reference - ordered prefix 28 | Coercion, // Most restrictive: no complex conversions 29 | } SubtypeConstraint; 30 | 31 | // Flag to indicate whether type match should inject coercion node 32 | typedef enum { 33 | NoCoerce, // Do not inject coercion node 34 | DoCoerce, // Inject coercion node if type matches 35 | } CoerceFlag; 36 | 37 | typedef struct Name Name; 38 | typedef struct INsTypeNode INsTypeNode; 39 | 40 | // Named type node header (most types are named) 41 | #define ITypeNodeHdr \ 42 | IExpNodeHdr; \ 43 | LLVMTypeRef llvmtype 44 | 45 | // Named type node interface (most types are named) 46 | // A named type needs to remember generated LLVM type ref for typenameuse nodes 47 | typedef struct ITypeNode { 48 | ITypeNodeHdr; 49 | } ITypeNode; 50 | 51 | // Return node's type's declaration node 52 | // (Note: only use after it has been type-checked) 53 | INode *itypeGetTypeDcl(INode *node); 54 | 55 | // Return node's type's declaration node (or vtexp if a ref or ptr) 56 | INode *itypeGetDerefTypeDcl(INode *node); 57 | 58 | // Look for named field/method in type 59 | INode *iTypeFindFnField(INode *type, Name *name); 60 | 61 | // Type check node, expecting it to be a type. Give error and return 0, if not. 62 | int itypeTypeCheck(TypeCheckState *pstate, INode **node); 63 | 64 | // Return 1 if nominally (or structurally) identical, 0 otherwise. 65 | // Nodes must both be types, but may be name use or declare nodes. 66 | int itypeIsSame(INode *node1, INode *node2); 67 | 68 | // Calculate hash for a type for use indexing the type table 69 | size_t itypeHash(INode *type); 70 | 71 | // Return 1 if nominally (or structurally) identical at runtime, 0 otherwise. 72 | // Nodes must both be types, but may be name use or declare nodes. 73 | int itypeIsRunSame(INode *node1, INode *node2); 74 | 75 | // Is totype equivalent or a subtype of fromtype 76 | TypeCompare itypeMatches(INode *totype, INode *fromtype, SubtypeConstraint constraint); 77 | 78 | // Return a type that is the supertype of both type nodes, or NULL if none found 79 | INode *itypeFindSuper(INode *type1, INode *type2); 80 | 81 | // Add type mangle info to buffer 82 | char *itypeMangle(char *bufp, INode *vtype); 83 | 84 | // Return true if type has a concrete and instantiable. 85 | // False for Opaque structs, traits, functions 86 | int itypeIsConcrete(INode *type); 87 | 88 | // Return true if type has zero size (e.g., void, empty struct) 89 | int itypeIsZeroSize(INode *type); 90 | 91 | // Return true if type implements move semantics 92 | int itypeIsMove(INode *type); 93 | 94 | // Return true if this is a generic type 95 | int itypeIsGenericType(INode *type); 96 | 97 | // Return drop function (or NULL) for type 98 | INode *itypeGetDropFnDcl(INode *type); 99 | 100 | #endif 101 | -------------------------------------------------------------------------------- /src/c-compiler/ir/namespace.c: -------------------------------------------------------------------------------- 1 | /** Hashed named nodes (see namespace.h) 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #include "nametbl.h" 9 | #include "namespace.h" 10 | #include "memory.h" 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | /** Modulo operation that calculates primary table entry from name's hash. 17 | * 'size' is always a power of 2 */ 18 | #define nameHashMod(hash, size) \ 19 | (assert(((size)&((size)-1))==0), (size_t) ((hash) & ((size)-1)) ) 20 | 21 | // Find the NameNode slot owned by a name 22 | #define namespaceFindSlot(slot, ns, namep) \ 23 | { \ 24 | size_t tbli; \ 25 | for (tbli = nameHashMod((namep)->hash, (ns)->avail);;) { \ 26 | slot = &(ns)->namenodes[tbli]; \ 27 | if (slot->name == NULL || slot->name == (namep)) \ 28 | break; \ 29 | tbli = nameHashMod(tbli + 1, (ns)->avail); \ 30 | } \ 31 | } 32 | 33 | // Grow the namespace, by either creating it or doubling its size 34 | void namespaceGrow(Namespace *namespace) { 35 | size_t oldTblAvail; 36 | NameNode *oldTable; 37 | size_t newTblMem; 38 | size_t oldslot; 39 | 40 | // Use avail for new table, otherwise double its size 41 | if (namespace->used == 0) { 42 | oldTblAvail = 0; 43 | } 44 | else { 45 | oldTblAvail = namespace->avail; 46 | namespace->avail <<= 1; 47 | } 48 | 49 | // Allocate and initialize new name table 50 | oldTable = namespace->namenodes; 51 | newTblMem = namespace->avail * sizeof(NameNode); 52 | namespace->namenodes = (NameNode*)memAllocBlk(newTblMem); 53 | memset(namespace->namenodes, 0, newTblMem); 54 | 55 | // Copy existing name slots to re-hashed positions in new table 56 | for (oldslot = 0; oldslot < oldTblAvail; oldslot++) { 57 | NameNode *oldslotp, *newslotp; 58 | oldslotp = &oldTable[oldslot]; 59 | if (oldslotp->name) { 60 | namespaceFindSlot(newslotp, namespace, oldslotp->name); 61 | newslotp->name = oldslotp->name; 62 | newslotp->node = oldslotp->node; 63 | } 64 | } 65 | // memFreeBlk(oldTable); 66 | } 67 | 68 | // Initialize a namespace with a specific number of slots 69 | void namespaceInit(Namespace *ns, size_t avail) { 70 | ns->used = 0; 71 | ns->avail = avail; 72 | ns->namenodes = NULL; 73 | namespaceGrow(ns); 74 | } 75 | 76 | // Return the node for a name (or NULL if none) 77 | INode *namespaceFind(Namespace *ns, Name *name) { 78 | NameNode *slotp; 79 | namespaceFindSlot(slotp, ns, name); 80 | return slotp->node; 81 | } 82 | 83 | // Add or change the node a name maps to 84 | void namespaceSet(Namespace *ns, Name *name, INode *node) { 85 | size_t cap = (ns->avail * 100) >> 7; 86 | if (ns->used > cap) 87 | namespaceGrow(ns); 88 | NameNode *slotp; 89 | namespaceFindSlot(slotp, ns, name); 90 | if (slotp->node == NULL) 91 | ++ns->used; 92 | slotp->name = name; 93 | slotp->node = node; 94 | } 95 | 96 | // Add the node a name maps to if no conflict and return NULL. 97 | // Otherwise, return the node already there 98 | INode *namespaceAdd(Namespace *ns, Name *name, INode *node) { 99 | // Don't add '_' (anonymous named) nodes, but report success 100 | if (name == anonName) 101 | return NULL; 102 | 103 | // If a node found there, return it 104 | NameNode *slotp; 105 | namespaceFindSlot(slotp, ns, name); 106 | if (slotp->node != NULL) 107 | return slotp->node; 108 | 109 | // Add node, if none found 110 | ++ns->used; 111 | slotp->name = name; 112 | slotp->node = node; 113 | 114 | // Grow if required, and return NULL 115 | size_t cap = (ns->avail * 100) >> 7; 116 | if (ns->used > cap) 117 | namespaceGrow(ns); 118 | return NULL; 119 | } 120 | -------------------------------------------------------------------------------- /src/c-compiler/ir/stmt/return.c: -------------------------------------------------------------------------------- 1 | /** Handling for return nodes 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #include "../ir.h" 9 | 10 | // Create a new return statement retnode 11 | BreakRetNode *newReturnNode() { 12 | BreakRetNode *node; 13 | newNode(node, BreakRetNode, ReturnTag); 14 | node->exp = NULL; 15 | node->block = NULL; 16 | node->dealias = NULL; 17 | return node; 18 | } 19 | 20 | // New return retnode with exp injected, and copy lex pos from it 21 | BreakRetNode *newReturnNodeExp(INode *exp) { 22 | BreakRetNode *node = newReturnNode(); 23 | node->exp = exp; 24 | inodeLexCopy((INode*)node, (INode*)exp); 25 | return node; 26 | } 27 | 28 | // Clone return 29 | INode *cloneReturnNode(CloneState *cstate, BreakRetNode *node) { 30 | BreakRetNode *newnode; 31 | newnode = memAllocBlk(sizeof(BreakRetNode)); 32 | memcpy(newnode, node, sizeof(BreakRetNode)); 33 | newnode->exp = cloneNode(cstate, node->exp); 34 | newnode->block = (BlockNode *)cloneDclFix((INode*)node->block); 35 | return (INode *)newnode; 36 | } 37 | 38 | // Serialize a return statement 39 | void returnPrint(BreakRetNode *node) { 40 | inodeFprint(node->tag == BlockRetTag? "blockret " : "return "); 41 | inodePrintNode(node->exp); 42 | } 43 | 44 | // Name resolution for return 45 | void returnNameRes(NameResState *nstate, BreakRetNode *retnode) { 46 | inodeNameRes(nstate, &retnode->exp); 47 | } 48 | 49 | // Type check for return statement 50 | // Related analysis for return elsewhere: 51 | // - Block ensures that return can only appear at end of block 52 | // - NameDcl turns fn block's final expression into an implicit return 53 | void returnTypeCheck(TypeCheckState *tstate, BreakRetNode *retnode) { 54 | // If we are returning the value from an 'if', recursively strip out any of its path's redundant 'return's 55 | if (retnode->exp->tag == IfTag) 56 | ifRemoveReturns((IfNode*)(retnode->exp)); 57 | 58 | // Ensure the vtype of the expression can be coerced to the function's declared return type 59 | // while processing the exp nodes 60 | FnSigNode *fnsig = (FnSigNode*)tstate->fn->vtype; 61 | if (fnsig->rettype->tag == TTupleTag && retnode->exp->tag == VTupleTag) { 62 | // Where return expression is an explicit value tuple, 63 | // we can safely perform implicit type coercions on individual tuple elements 64 | Nodes *retnodes = ((TupleNode*)retnode->exp)->elems; 65 | Nodes *rettypes = ((TupleNode*)fnsig->rettype)->elems; 66 | if (rettypes->used > retnodes->used) { 67 | errorMsgNode(retnode->exp, ErrorBadTerm, "Not enough return values"); 68 | return; 69 | } 70 | uint32_t retcnt; 71 | INode **rettypesp; 72 | INode **retnodesp = &nodesGet(retnodes, 0); 73 | for (nodesFor(rettypes, retcnt, rettypesp)) { 74 | if (!iexpTypeCheckCoerce(tstate, *rettypesp, retnodesp++)) 75 | errorMsgNode(*(retnodesp - 1), ErrorInvType, "Return value's type does not match fn return type"); 76 | } 77 | // Establish the type of the tuple (from the expected return value types) 78 | ((TupleNode *)retnode->exp)->vtype = fnsig->rettype; 79 | } 80 | else if (!iexpTypeCheckCoerce(tstate, fnsig->rettype, &retnode->exp)) { 81 | errorMsgNode((INode*)retnode, ErrorInvType, "Return expression type does not match return type on function"); 82 | errorMsgNode((INode*)fnsig->rettype, ErrorInvType, "This is the declared function's return type"); 83 | } 84 | 85 | // Have return node point to function block that is "breaks" out of 86 | // Also, add return node to that block's list of returns (generation needs this to help with inline functions) 87 | BlockNode *fnblock = retnode->block = (BlockNode*)tstate->fn->value; 88 | if (tstate->fn->flags & FlagInline) { 89 | if (!fnblock->breaks) 90 | fnblock->breaks = newNodes(2); 91 | nodesAdd(&fnblock->breaks, (INode*)retnode); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/c-compiler/ir/ir.h: -------------------------------------------------------------------------------- 1 | /** Intermediate Representation (IR) structures and macros 2 | * 3 | * The IR, together with the name table, is the skeleton of the compiler. 4 | * It connects together every stage: 5 | * 6 | * - The parser transforms programs into IR 7 | * - The semantic analysis walks the IR nodes over multiple passes 8 | * - Macro and template expansion happens via IR cloning 9 | * - Generation transforms IR into LLVM IR 10 | * 11 | * The IR is comprised of heterogeneous nodes that share common INodeHdr info. 12 | * In some cases, it is possible for several distinct node types to share an 13 | * identical data structure (e.g., statement expression and return). 14 | * 15 | * This include file will pull in the include files for all node types, including types. 16 | * It also defines the structures needed for semantic analysis passes. 17 | * 18 | * @file 19 | * 20 | * This source file is part of the Cone Programming Language C compiler 21 | * See Copyright Notice in conec.h 22 | */ 23 | 24 | #ifndef ir_h 25 | #define ir_h 26 | 27 | #include 28 | 29 | #include 30 | 31 | #include "../shared/memory.h" 32 | #include "nodes.h" 33 | #include "nodelist.h" 34 | #include "namespace.h" 35 | typedef struct Name Name; // ../nametbl.h 36 | typedef struct Lexer Lexer; // ../../parser/lexer.h 37 | typedef struct NameResState NameResState; 38 | typedef struct TypeCheckState TypeCheckState; 39 | typedef struct GenericInfo GenericInfo; 40 | 41 | // Interfaces & headers shared across nodes 42 | #include "inode.h" 43 | #include "name.h" 44 | #include "itype.h" 45 | #include "iexp.h" 46 | #include "instype.h" 47 | #include "clone.h" 48 | #include "flow.h" 49 | 50 | // These includes are needed by all node handling 51 | #include "../parser/lexer.h" 52 | #include "../shared/error.h" 53 | #include "nametbl.h" 54 | #include "typetbl.h" 55 | #include "../shared/memory.h" 56 | 57 | #include "types/typedef.h" 58 | #include "types/ttuple.h" 59 | #include "types/permission.h" 60 | #include "types/enum.h" 61 | #include "types/lifetime.h" 62 | #include "types/fnsig.h" 63 | #include "types/number.h" 64 | #include "types/reference.h" 65 | #include "types/arrayref.h" 66 | #include "types/pointer.h" 67 | #include "types/struct.h" 68 | #include "types/region.h" 69 | #include "types/array.h" 70 | #include "types/void.h" 71 | 72 | #include "exp/block.h" 73 | #include "stmt/module.h" 74 | #include "stmt/break.h" 75 | #include "stmt/continue.h" 76 | #include "stmt/fielddcl.h" 77 | #include "stmt/fndcl.h" 78 | #include "stmt/return.h" 79 | #include "stmt/import.h" 80 | #include "stmt/intrinsic.h" 81 | #include "stmt/swap.h" 82 | #include "stmt/const.h" 83 | #include "stmt/vardcl.h" 84 | 85 | #include "exp/borrow.h" 86 | #include "exp/allocate.h" 87 | #include "exp/assign.h" 88 | #include "exp/cast.h" 89 | #include "exp/deref.h" 90 | #include "exp/nameuse.h" 91 | #include "exp/fncall.h" 92 | #include "exp/if.h" 93 | #include "exp/literal.h" 94 | #include "exp/namedval.h" 95 | #include "exp/arraylit.h" 96 | #include "exp/typelit.h" 97 | #include "exp/logic.h" 98 | #include "exp/sizeof.h" 99 | #include "exp/vtuple.h" 100 | 101 | #include "meta/genvardcl.h" 102 | #include "meta/macro.h" 103 | #include "meta/generic.h" 104 | 105 | #include "stmt/program.h" 106 | 107 | #include "../corelib/corelib.h" 108 | 109 | // Context used for name resolution pass 110 | typedef struct NameResState { 111 | ModuleNode *mod; // Current module 112 | INode *typenode; // Current type (e.g., struct) 113 | BlockNode *loopblock; // Most current loop block (or NULL) 114 | uint16_t scope; // The current block scope (0=global, 1=fnsig, 2+=blocks) 115 | uint16_t flags; // e.g., PassWithinWhile 116 | } NameResState; 117 | 118 | #define TypeCheckLoopMax 256 119 | #define TypeCheckBlockMax 1024 120 | 121 | // Context used for type check pass 122 | typedef struct TypeCheckState { 123 | INode *typenode; // Current type (e.g., struct) 124 | FnDclNode *fn; // The function and its signature/block (for returned processing) 125 | uint16_t scope; // Current block scope level 126 | } TypeCheckState; 127 | 128 | #endif 129 | -------------------------------------------------------------------------------- /src/c-compiler/ir/typetbl.c: -------------------------------------------------------------------------------- 1 | /** Global Type Table. 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #include "typetbl.h" 9 | #include "memory.h" 10 | 11 | #include 12 | #include 13 | 14 | // Public globals 15 | size_t gTypeTblInitSize = 4096; // Initial maximum number of unique types (must be power of 2) 16 | unsigned int gTypeTblUtil = 50; // % utilization that triggers doubling of table 17 | 18 | // Private globals 19 | static TypeTblEntry *gTypeTable = NULL; // The type table array 20 | static size_t gTypeTblAvail = 0; // Number of allocated type table slots (power of 2) 21 | static size_t gTypeTblCeil = 0; // Ceiling that triggers table growth 22 | static size_t gTypeTblUsed = 0; // Number of type table slots used 23 | 24 | /** Modulo operation that calculates primary table entry from name's hash. 25 | * 'size' is always a power of 2 */ 26 | #define typeHashMod(hash, size) \ 27 | (assert(((size)&((size)-1))==0), (size_t) ((hash) & ((size)-1)) ) 28 | 29 | /** Calculate index into name table for a name using linear probing 30 | * The table's slot at index is either empty or matches the provided name/hash 31 | */ 32 | #define typetblFindSlot(tblp, hash, type) \ 33 | { \ 34 | size_t tbli; \ 35 | for (tbli = typeHashMod(hash, gTypeTblAvail);;) { \ 36 | tblp = &gTypeTable[tbli]; \ 37 | if (tblp->type==NULL || (tblp->hash == hash && itypeIsRunSame(tblp->type, type))) \ 38 | break; \ 39 | tbli = typeHashMod(tbli + 1, gTypeTblAvail); \ 40 | } \ 41 | } 42 | 43 | /** Grow the type table, by either creating it or doubling its size */ 44 | void typetblGrow() { 45 | size_t oldTblAvail; 46 | TypeTblEntry *oldTable; 47 | size_t newTblMem; 48 | size_t oldslot; 49 | 50 | // Preserve old table info 51 | oldTable = gTypeTable; 52 | oldTblAvail = gTypeTblAvail; 53 | 54 | // Allocate and initialize new name table 55 | gTypeTblAvail = oldTblAvail==0? gTypeTblInitSize : oldTblAvail<<1; 56 | gTypeTblCeil = (gTypeTblUtil * gTypeTblAvail) / 100; 57 | newTblMem = gTypeTblAvail * sizeof(TypeTblEntry); 58 | gTypeTable = (TypeTblEntry*) memAllocBlk(newTblMem); 59 | memset(gTypeTable, 0, newTblMem); // Fill with NULL pointers & 0s 60 | 61 | // Copy existing name slots to re-hashed positions in new table 62 | for (oldslot=0; oldslot < oldTblAvail; oldslot++) { 63 | TypeTblEntry *oldslotp, *newslotp; 64 | oldslotp = &oldTable[oldslot]; 65 | if (oldslotp->type) { 66 | INode *type = oldslotp->type; 67 | size_t hash = oldslotp->hash; 68 | typetblFindSlot(newslotp, hash, type); 69 | newslotp->hash = oldslotp->hash; 70 | newslotp->type = oldslotp->type; 71 | newslotp->normal = oldslotp->normal; 72 | } 73 | } 74 | // memFreeBlk(oldTable); 75 | } 76 | 77 | /** Get pointer to type's normalized metadata in Global Type Table matching type. 78 | * For unknown type, this allocates memory for the metadata and adds it to type table. */ 79 | void *typetblFind(INode *type, void *(*allocfn)()) { 80 | TypeTblEntry *slotp; 81 | 82 | // Hash provide string into table 83 | size_t hash = itypeHash(type); 84 | typetblFindSlot(slotp, hash, type); 85 | 86 | // If not already a name, allocate memory for string and add to table 87 | if (slotp->type == NULL) { 88 | // Double table if it has gotten too full 89 | if (++gTypeTblUsed >= gTypeTblCeil) { 90 | typetblGrow(); 91 | typetblFindSlot(slotp, hash, type); 92 | } 93 | 94 | // Allocate and populate type info 95 | slotp->type = type; 96 | slotp->hash = hash; 97 | slotp->normal = allocfn(); 98 | } 99 | return slotp->normal; 100 | } 101 | 102 | // Return size of unused space for name table 103 | size_t typetblUnused() { 104 | return (gTypeTblAvail-gTypeTblUsed)*sizeof(TypeTblEntry); 105 | } 106 | 107 | // Initialize name table 108 | void typetblInit() { 109 | typetblGrow(); 110 | } 111 | -------------------------------------------------------------------------------- /src/c-compiler/shared/error.h: -------------------------------------------------------------------------------- 1 | /** Error handling 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #ifndef error_h 9 | #define error_h 10 | 11 | typedef struct INode INode; // ../ast/ast.h 12 | 13 | // Exit error codes 14 | enum ErrorCode { 15 | // Terminating errors 16 | ExitSuccess, 17 | ExitError, // Program fails to compile due to caught errors 18 | ExitNF, // Could not find specified source files 19 | ExitMem, // Out of memory 20 | ExitOpts, // Invalid compiler options 21 | ExitIndent, // Too many indent levels in lexer 22 | 23 | // Non-terminating errors 24 | ErrorCode = 1000, 25 | ErrorBadTok, // Bad character starting an unknown token 26 | ErrorGenErr, // Failure to perform generation activity 27 | ErrorNoSemi, // Missing semicolon 28 | ErrorNoLCurly, // Missing left curly brace 29 | ErrorNoRCurly, // Missing right curly brace 30 | ErrorBadTerm, // Invalid term - something other than var, lit, etc. 31 | ErrorBadGloStmt, // Invalid global area type, var or function statement 32 | ErrorDupImpl, // Function already has another implementation 33 | ErrorNoLParen, // Expected left parenthesis not found 34 | ErrorNoRParen, // Expected right parenthesis not found 35 | ErrorDupName, // Duplicate name declaration 36 | ErrorNoName, // Name is required but not provided 37 | ErrorInvType, // Types do not match correctly 38 | ErrorNoIdent, // Identifier expected but not provided 39 | ErrorNotLit, // Value can only be a literal 40 | ErrorBadLval, // Expression is not an lval 41 | ErrorNoMut, // Mutation is not allowed 42 | ErrorNotFn, // Not a function 43 | ErrorUnkName, // Unknown name (no declaration exists) 44 | ErrorNoType, // No type specified (or inferrable) 45 | ErrorNoInit, // Parm didn't specify required default value 46 | ErrorFewArgs, // Too few arguments specified 47 | ErrorManyArgs, // Too many arguments specified 48 | ErrorNoMbr, // Method/field not specified 49 | ErrorNoMeth, // No such method defined by the object's type 50 | ErrorRetNotLast, // Return was found not at the end of the block 51 | ErrorNoRet, // Return value expected but not given 52 | ErrorNoElse, // Missing 'else' branch 53 | ErrorNoLoop, // 'break' or 'continue' allowed only in while/each loop 54 | ErrorNoVtype, // Missing value type 55 | ErrorNotPtr, // Not a pointer 56 | ErrorNotLval, // Not an lval 57 | ErrorAddr, // Invalid expr to get an addr (&) of 58 | ErrorBadPerm, // Permission not allowed 59 | ErrorNoFlds, // Expression's type does not support fields 60 | ErrorBadAlloc, // Missing valid alloc methods 61 | ErrorNoDbl, // Missing '::' 62 | ErrorNoVar, // Missing variable name 63 | ErrorNoEof, // Missing end-of-file 64 | ErrorNoImpl, // Function must be implemented 65 | ErrorBadImpl, // Function must not be implemented 66 | ErrorNotPublic, // Method is not public 67 | ErrorBadMeth, // Methods/fields not supported 68 | ErrorNotTyped, // Expected a value that has a type 69 | ErrorBadIndex, // Bad index/slice on array/ref 70 | ErrorBadArray, // Bad array 71 | ErrorBadSlice, // Bad slice type 72 | ErrorMove, // Move error of some kind 73 | ErrorRecurse, // Recursive type error 74 | ErrorBadStmt, // Bad statement 75 | ErrorBadElems, // Inconsistent tuple elements 76 | 77 | // Warnings 78 | WarnCode = 3000, 79 | WarnName, // Unnecessary name 80 | WarnIndent, // Inconsistent indent character 81 | WarnCopy, // Unsafe attempt to copy a CopyMethod or CopyMove typed value 82 | WarnLoop, // Infinite loop with no break 83 | 84 | // Uncounted 85 | Uncounted = 9000, 86 | }; 87 | 88 | extern int errors; 89 | 90 | // Send an error message to stderr 91 | void errorExit(int exitcode, const char *msg, ...); 92 | void errorMsgNode(INode *node, int code, const char *msg, ...); 93 | void errorMsgLex(int code, const char *msg, ...); 94 | void errorMsg(int code, const char *msg, ...); 95 | void errorSummary(); 96 | 97 | #endif 98 | -------------------------------------------------------------------------------- /src/c-compiler/ir/exp/arraylit.c: -------------------------------------------------------------------------------- 1 | /** Handling for array literals 2 | * @file 3 | * 4 | * This source file is part of the Cone Programming Language C compiler 5 | * See Copyright Notice in conec.h 6 | */ 7 | 8 | #include "../ir.h" 9 | 10 | // Note: Creation, serialization and name checking are done with array type logic, 11 | // as we don't yet know whether [] is a type or an array literal 12 | 13 | // Type check an array literal 14 | void arrayLitTypeCheckDimExp(TypeCheckState *pstate, ArrayNode *arrlit) { 15 | 16 | // Handle array literal "fill" format: [dimen, fill-value] 17 | if (arrlit->dimens->used > 0) { 18 | 19 | // Ensure only one constant integer dimension 20 | if (arrlit->dimens->used > 1) { 21 | errorMsgNode((INode*)arrlit, ErrorBadArray, "Array literal may only specify one dimension"); 22 | return; 23 | } 24 | INode **dimnodep = &nodesGet(arrlit->dimens, 0); 25 | INode *dimnode = *dimnodep; 26 | if (dimnode->tag == ULitTag) 27 | ((ULitNode*)dimnode)->vtype = (INode*)usizeType; // Force type 28 | // Ensure it coerces to usize 29 | if (iexpTypeCheckCoerce(pstate, (INode*)usizeType, dimnodep) != 1) 30 | errorMsgNode((INode*)arrlit, ErrorBadArray, "Array literal dimension must coerce to usize"); 31 | 32 | // Handle and type the single fill value 33 | if (arrlit->elems->used != 1 || !isExpNode(nodesGet(arrlit->elems, 0))) { 34 | errorMsgNode((INode*)arrlit, ErrorBadArray, "Array fill value may only be one value"); 35 | return; 36 | } 37 | INode **elemnodep = &nodesGet(arrlit->elems, 0); 38 | size_t dimsize = 0; 39 | if (dimnode->tag != ULitTag) { 40 | while (dimnode->tag == VarNameUseTag) { 41 | INode *dclnode = ((NameUseNode*)dimnode)->dclnode; 42 | if (dclnode->tag == ConstDclTag) 43 | dimnode = ((ConstDclNode*)dclnode)->value; 44 | else 45 | break; 46 | } 47 | } 48 | if (dimnode->tag == ULitTag) 49 | dimsize = (size_t)((ULitNode*)dimnode)->uintlit; 50 | if (iexpTypeCheckAny(pstate, elemnodep)) { 51 | arrlit->vtype = (INode*)newArrayNodeTyped((INode*)arrlit, 52 | dimsize, ((IExpNode*)*elemnodep)->vtype); 53 | } 54 | return; 55 | } 56 | 57 | // Otherwise handle multi-value array literal 58 | if (arrlit->elems->used == 0) { 59 | errorMsgNode((INode*)arrlit, ErrorBadArray, "Array literal list may not be empty"); 60 | return; 61 | } 62 | 63 | // Ensure all elements are consistently typed (matching first element's type) 64 | INode *matchtype = unknownType; 65 | INode **nodesp; 66 | uint32_t cnt; 67 | for (nodesFor(arrlit->elems, cnt, nodesp)) { 68 | if (iexpTypeCheckAny(pstate, nodesp) == 0) 69 | continue; 70 | if (matchtype == unknownType) { 71 | // Get element type from first element 72 | // Type of array literal is: array of elements whose type matches first value 73 | matchtype = ((IExpNode*)*nodesp)->vtype; 74 | } 75 | else if (!itypeIsSame(((IExpNode*)*nodesp)->vtype, matchtype)) 76 | errorMsgNode((INode*)*nodesp, ErrorBadArray, "Inconsistent type of array literal value"); 77 | } 78 | arrlit->vtype = (INode*)newArrayNodeTyped((INode*)arrlit, arrlit->elems->used, matchtype); 79 | } 80 | 81 | // The default type check 82 | void arrayLitTypeCheck(TypeCheckState *pstate, ArrayNode *arrlit) { 83 | 84 | // In the default scenario (not as part of region allocation), 85 | // we must insist that array literal's dimension is a constant unsigned integer 86 | if (arrlit->dimens->used > 0 && !litIsLiteral(nodesGet(arrlit->dimens, 0))) { 87 | errorMsgNode((INode*)arrlit, ErrorBadArray, "Array literal dimension value must be a constant"); 88 | } 89 | arrayLitTypeCheckDimExp(pstate, arrlit); 90 | } 91 | 92 | // Is the array actually a literal? 93 | int arrayLitIsLiteral(ArrayNode *node) { 94 | INode **nodesp; 95 | uint32_t cnt; 96 | for (nodesFor(node->elems, cnt, nodesp)) { 97 | INode *elem = *nodesp; 98 | if (!litIsLiteral(elem)) 99 | return 0; 100 | } 101 | return 1; 102 | } 103 | -------------------------------------------------------------------------------- /src/c-compiler/parser/parsehelper.c: -------------------------------------------------------------------------------- 1 | /** Parser helpers 2 | * @file 3 | * 4 | * - Statement end handling (; and inference) 5 | * - Block start and end (indented vs. free-flow) 6 | * - Closing paren vs. bracket 7 | * 8 | * This source file is part of the Cone Programming Language C compiler 9 | * See Copyright Notice in conec.h 10 | */ 11 | 12 | #include "parser.h" 13 | #include "../ir/ir.h" 14 | #include "../shared/memory.h" 15 | #include "../shared/error.h" 16 | #include "../shared/fileio.h" 17 | #include "../ir/nametbl.h" 18 | #include "../coneopts.h" 19 | #include "lexer.h" 20 | 21 | #include 22 | #include 23 | 24 | // Skip to next statement for error recovery 25 | void parseSkipToNextStmt() { 26 | // Ensure we are always moving forwards, line by line 27 | if (lexIsEndOfLine() && !lexIsToken(SemiToken) && !lexIsToken(EofToken) && !lexIsToken(RCurlyToken)) 28 | lexNextToken(); 29 | while (1) { 30 | // Consume semicolon as end-of-statement 31 | if (lexIsToken(SemiToken)) { 32 | lexNextToken(); 33 | return; 34 | } 35 | // Treat end-of-line, end-of-file, or '}' as end-of-statement 36 | // (clearly end-of-line might *not* be end-of-statement) 37 | if (lexIsEndOfLine() || lexIsToken(EofToken) || lexIsToken(RCurlyToken)) 38 | return; 39 | 40 | lexNextToken(); 41 | } 42 | } 43 | 44 | // Is this end-of-statement? if ';', '}', or end-of-file 45 | int parseIsEndOfStatement() { 46 | return (lex->toktype == SemiToken || lex->toktype == RCurlyToken || lex->toktype == EofToken 47 | || lexIsStmtBreak()); 48 | } 49 | 50 | // We expect optional semicolon since statement has run its course 51 | void parseEndOfStatement() { 52 | // Consume semicolon as end-of-statement signifier, if found 53 | if (lex->toktype == SemiToken) { 54 | lexNextToken(); 55 | return; 56 | } 57 | // If no semi-colon specified, we expect to be at end-of-line, 58 | // unless next token is '}' or end-of-file 59 | if (!lexIsEndOfLine() && lex->toktype != RCurlyToken && lex->toktype != EofToken) 60 | errorMsgLex(ErrorNoSemi, "Statement finished? Expected semicolon or end of line."); 61 | } 62 | 63 | // Return true on '{' or ':' 64 | int parseHasBlock() { 65 | return (lex->toktype == LCurlyToken || lex->toktype == ColonToken); 66 | } 67 | 68 | // Expect a block to start, consume its token and set lexer mode 69 | void parseBlockStart() { 70 | if (lex->toktype == LCurlyToken) { 71 | lexNextToken(); 72 | lexBlockStart(FreeFormBlock); 73 | return; 74 | } 75 | else if (lex->toktype == ColonToken) { 76 | lexNextToken(); 77 | lexBlockStart(lexIsEndOfLine() ? SigIndentBlock : SameStmtBlock); 78 | return; 79 | } 80 | 81 | // Generate error and try to recover 82 | errorMsgLex(ErrorNoLCurly, "Expected ':' or '{' to start a block"); 83 | if (lexIsEndOfLine() && lex->curindent > lex->stmtindent) { 84 | lexBlockStart(SigIndentBlock); 85 | return; 86 | } 87 | // Skip forward to find something we can use 88 | while (1) { 89 | if (lexIsToken(LCurlyToken) || lexIsToken(ColonToken)) { 90 | parseBlockStart(); 91 | return; 92 | } 93 | if (lexIsToken(EofToken)) 94 | break; 95 | lexNextToken(); 96 | } 97 | } 98 | 99 | // Are we at end of block yet? If so, consume token and reset lexer mode 100 | int parseBlockEnd() { 101 | if (lexIsToken(RCurlyToken) && lex->blkStack[lex->blkStackLvl].blkmode == FreeFormBlock) { 102 | lexNextToken(); 103 | lexBlockEnd(); 104 | return 1; 105 | } 106 | if (lexIsBlockEnd()) { 107 | lexBlockEnd(); 108 | return 1; 109 | } 110 | if (lexIsToken(EofToken)) { 111 | errorMsgLex(ErrorNoRCurly, "Expected end of block (e.g., '}')"); 112 | return 1; 113 | } 114 | return 0; 115 | } 116 | 117 | // Expect closing token (e.g., right parenthesis). If not found, search for it or '}' or ';' 118 | void parseCloseTok(uint16_t closetok) { 119 | if (!lexIsToken(closetok)) 120 | errorMsgLex(ErrorNoRParen, "Expected right parenthesis - skipping forward to find it"); 121 | while (!lexIsToken(closetok)) { 122 | if (lexIsToken(EofToken) || lexIsToken(SemiToken) || lexIsToken(RCurlyToken)) 123 | return; 124 | lexNextToken(); 125 | } 126 | lexNextToken(); 127 | lexDecrParens(); 128 | } 129 | --------------------------------------------------------------------------------