Author: mesyeti <mesyeti@mesyeti.uk>
add structures
basic/source/compiler.c | 16 +- basic/source/compiler.h | 1 basic/source/frontend/c89.c | 54 ++++++++-- basic/source/lexer.c | 19 +++ basic/source/lexer.h | 5 basic/source/main.c | 9 + basic/source/parser.c | 179 ++++++++++++++++++++++++++++++++-- basic/source/parser.h | 34 ++++++ basic/source/semanticAnalysis.c | 87 ++++++++++++++++ basic/source/state.c | 6 + basic/source/state.h | 9 + basic/test.bas | 28 ++-- basic/test2.bas | 1
diff --git a/basic/source/compiler.c b/basic/source/compiler.c index b37cd3093c6494615a61343fbc5a6a43dd374bb0..d990335cd0f2ef79f3a16773d0b98f4c3add6ac2 100644 --- a/basic/source/compiler.c +++ b/basic/source/compiler.c @@ -20,6 +20,7 @@ case NODE_FUNC_DEF: frontend.compileFuncDef(&node->funcDef); break; case NODE_DIM: frontend.compileDim(&node->dim); break; case NODE_EXTERN: frontend.compileExtern(&node->external); break; case NODE_IF: frontend.compileIf(&node->ifStat); break; + case NODE_WHILE: frontend.compileWhile(&node->whileStat); break; case NODE_BINARY_OP: { if (node->bin.op == TOKEN_ASSIGN) { frontend.compileAssign(&node->bin); @@ -35,11 +36,14 @@ void Compiler_CompileTopNode(Node* node, bool inFunc) { if (inFunc) { switch (node->i.type) { - case NODE_FUNC_DEF: break; - case NODE_DIM: break; - case NODE_EXTERN: break; + case NODE_FUNC_DEF: break; + case NODE_DIM: break; + case NODE_EXTERN: break; + case NODE_TYPE_DEF: break; + case NODE_TYPE_BLOCK: break; case NODE_FUNC_CALL: frontend.compileFuncCall(&node->funcCall); break; case NODE_IF: frontend.compileIf(&node->ifStat); break; + case NODE_WHILE: frontend.compileWhile(&node->whileStat); break; case NODE_BINARY_OP: { if (node->bin.op == TOKEN_ASSIGN) { frontend.compileAssign(&node->bin); @@ -53,9 +57,9 @@ } } else { switch (node->i.type) { - case NODE_FUNC_DEF: frontend.compileFuncDef(&node->funcDef); break; - case NODE_DIM: frontend.compileDim(&node->dim); break; - case NODE_EXTERN: frontend.compileExtern(&node->external); break; + case NODE_FUNC_DEF: frontend.compileFuncDef(&node->funcDef); break; + case NODE_DIM: frontend.compileDim(&node->dim); break; + case NODE_EXTERN: frontend.compileExtern(&node->external); break; default: break; } } diff --git a/basic/source/compiler.h b/basic/source/compiler.h index 26db868dd7c4acf2e93fcffb7977d6768676ccc0..a6dea3c1f4865a22ba92efdef4d07d16faa865e0 100644 --- a/basic/source/compiler.h +++ b/basic/source/compiler.h @@ -12,6 +12,7 @@ void (*compileFuncCall)(FuncCallNode* node); void (*compileExtern)(ExternNode* node); void (*compileIf)(IfNode* node); void (*compileAssign)(BinaryNode* node); + void (*compileWhile)(WhileNode* node); } Frontend; void Frontend_Init(Frontend p_frontend); diff --git a/basic/source/frontend/c89.c b/basic/source/frontend/c89.c index 8b10294ed608e26c89721bd58f5097465fcdd00f..422a6ce4fb8945257103789f2b856ad2247a0de1 100644 --- a/basic/source/frontend/c89.c +++ b/basic/source/frontend/c89.c @@ -78,8 +78,11 @@ static void CompileDim(DimNode* node) { if (inMain) return; + UsedType usedType = SemanticAnalysis_NodeAsUsedType(node->varType); + Type* type = &state.types[usedType.typeIdx]; + CompileType(node->varType); - fprintf(out, " %s;\n", node->name); + fprintf(out, " %s = %s;\n", node->name, type->type == TYPE_PRIM? "0" : "{0}"); } static void CompileExprNode(Node* node); @@ -117,6 +120,7 @@ case TOKEN_EQUAL: fprintf(out, "=="); break; case TOKEN_LESS: fprintf(out, "<"); break; case TOKEN_GREATER: fprintf(out, ">"); break; case TOKEN_ASSIGN: fprintf(out, "="); break; + case TOKEN_DOT: fprintf(out, "."); break; default: assert(0); } @@ -207,20 +211,47 @@ CompileExprNode(node->right); fprintf(out, ";\n"); } +static void CompileWhile(WhileNode* node) { + fprintf(out, "while ("); + CompileExprNode(node->condition); + fprintf(out, ") {\n"); + + for (size_t i = 0; i < node->bodyLen; ++ i) { + Compiler_CompileBodyNode(&node->body[i]); + } + + fprintf(out, "}\n"); +} + +static void CompileStruct(Type* type) { + // fprintf(out, "typedef %s {\n", node->isUnion? "union" : "struct"); + fprintf(out, "typedef struct {\n"); + + for (size_t i = 0; i < type->structLen; ++ i) { + fprintf(out, " "); + CompileUsedType(type->structure[i].type); + fprintf(out, " %s;\n", type->structure[i].name); + } + + fprintf(out, "} nitron_%s;", type->name); +} + Frontend Frontend_C89(void) { out = fopen("out.c", "w"); inMain = false; fprintf(out, "#include <stdint.h>\n"); fprintf(out, "#include <stdlib.h>\n"); + fprintf(out, "#include <string.h>\n"); // define all types for (size_t i = 0; i < state.typeNum; ++ i) { Type* type = &state.types[i]; switch (type->type) { - case TYPE_PRIM: CompilePrim(type); break; - case TYPE_UNIT: break; + case TYPE_PRIM: CompilePrim(type); break; + case TYPE_UNIT: break; + case TYPE_STRUCT: CompileStruct(type); break; default: assert(0); } } @@ -234,13 +265,14 @@ fprintf(out, " nitron_%s;\n", var->name); } return (Frontend) { - .finish = &Finish, - .beginMain = &BeginMain, - .compileFuncDef = &CompileFuncDef, - .compileDim = &CompileDim, - .compileFuncCall = &CompileFuncCall, - .compileExtern = &CompileExtern, - .compileIf = &CompileIf, - .compileAssign = &CompileAssign + .finish = &Finish, + .beginMain = &BeginMain, + .compileFuncDef = &CompileFuncDef, + .compileDim = &CompileDim, + .compileFuncCall = &CompileFuncCall, + .compileExtern = &CompileExtern, + .compileIf = &CompileIf, + .compileAssign = &CompileAssign, + .compileWhile = &CompileWhile }; } diff --git a/basic/source/lexer.c b/basic/source/lexer.c index 8e53cee20d36e2e919285f51190398e5fad1a7dc..ff940fc2b707be22ff79e91fa07f5f562395f927 100644 --- a/basic/source/lexer.c +++ b/basic/source/lexer.c @@ -24,6 +24,7 @@ case '\n': case '\t': case '(': case ')': + case '.': case ',': case '+': case '-': @@ -33,7 +34,8 @@ case '%': case '=': case '<': case '>': - case '\'': return true; + case '\'': + case ';': return true; default: return false; } } @@ -96,6 +98,7 @@ return LEXER_TOKEN; } case '(': *token = TOKEN(TOKEN_LPAREN, NULL); return LEXER_TOKEN; case ')': *token = TOKEN(TOKEN_RPAREN, NULL); return LEXER_TOKEN; + case '.': *token = TOKEN(TOKEN_DOT, NULL); return LEXER_TOKEN; case ',': *token = TOKEN(TOKEN_COMMA, NULL); return LEXER_TOKEN; case ';': *token = TOKEN(TOKEN_LINE, NULL); return LEXER_TOKEN; case '+': *token = TOKEN(TOKEN_ADD, NULL); return LEXER_TOKEN; @@ -167,7 +170,11 @@ {"ptr", TOKEN_PTR}, {"end", TOKEN_END}, {"if", TOKEN_IF}, {"then", TOKEN_THEN}, - {"else", TOKEN_ELSE} + {"else", TOKEN_ELSE}, + {"while", TOKEN_WHILE}, + {"do", TOKEN_DO}, + {"type", TOKEN_TYPE}, + {"union", TOKEN_UNION} }; for (size_t i = 0; i < sizeof(keywords) / sizeof(Keyword); ++ i) { @@ -195,12 +202,20 @@ case TOKEN_AS: return "as"; case TOKEN_QUIT: return "quit"; case TOKEN_PTR: return "ptr"; case TOKEN_END: return "end"; + case TOKEN_IF: return "if"; + case TOKEN_THEN: return "then"; + case TOKEN_ELSE: return "else"; + case TOKEN_WHILE: return "while"; + case TOKEN_DO: return "do"; + case TOKEN_TYPE: return "type"; + case TOKEN_UNION: return "union"; case TOKEN_IDENTIFIER: return "identifier"; case TOKEN_STRING: return "string"; case TOKEN_INT: return "int"; case TOKEN_LINE: return "line"; case TOKEN_LPAREN: return "lparen"; case TOKEN_RPAREN: return "rparen"; + case TOKEN_DOT: return "dot"; case TOKEN_COMMA: return "comma"; case TOKEN_ADD: return "add"; case TOKEN_SUBTRACT: return "subtract"; diff --git a/basic/source/lexer.h b/basic/source/lexer.h index 3b13d51817a87a47534307f4d0cf0b9087b8721e..dcc26c65179b83f62e0d450574587b1c93411605 100644 --- a/basic/source/lexer.h +++ b/basic/source/lexer.h @@ -20,6 +20,10 @@ TOKEN_END, TOKEN_IF, TOKEN_THEN, TOKEN_ELSE, + TOKEN_WHILE, + TOKEN_DO, + TOKEN_TYPE, + TOKEN_UNION, // misc TOKEN_IDENTIFIER, @@ -30,6 +34,7 @@ // characters TOKEN_LPAREN, TOKEN_RPAREN, + TOKEN_DOT, TOKEN_COMMA, // operators diff --git a/basic/source/main.c b/basic/source/main.c index 6c2baa46efe19dc613bea1c4f69f295514d9fa0a..9df35583c37a392556ade14513c63b1bd522fac0 100644 --- a/basic/source/main.c +++ b/basic/source/main.c @@ -12,6 +12,7 @@ const char* source = NULL; bool printNodes = false; bool printTokens = false; + bool printState = false; if (argc == 1) { printf( @@ -33,6 +34,9 @@ printNodes = true; } else if (strcmp(argv[i], "--dl") == 0) { printTokens = true; + } + else if (strcmp(argv[i], "--ds") == 0) { + printState = true; } else { fprintf(stderr, "Unknown flag: %s\n", argv[i]); @@ -69,6 +73,11 @@ SemanticAnalysis_Init(8); for (size_t i = 0; i < len; ++ i){ SemanticAnalysis_Analyse(&ret[i]); + } + + if (printState) { + State_DumpInfo(); + return 0; } Compiler_Init(ret, len); diff --git a/basic/source/parser.c b/basic/source/parser.c index 84b829dee914e7daea8e86999bf6b0330472b56f..d15c1cc7833cc07e123e42265fc21629e2c56161 100644 --- a/basic/source/parser.c +++ b/basic/source/parser.c @@ -225,13 +225,34 @@ return left; } +static Node ParseDot(Parser* p) { + Node left = ParseComparison(p); + + while (p->tokens[p->i].type == TOKEN_DOT) { + TokenType op = p->tokens[p->i].type; + Advance(p); + Node right = ParseComparison(p); + + Node* leftPtr = SafeMalloc(sizeof(Node)); + Node* rightPtr = SafeMalloc(sizeof(Node)); + *leftPtr = left; + *rightPtr = right; + + left.bin = (BinaryNode) { + INFO(NODE_BINARY_OP), leftPtr, rightPtr, op + }; + } + + return left; +} + static Node ParseAssign(Parser* p) { - Node left = ParseComparison(p); + Node left = ParseDot(p); while (p->tokens[p->i].type == TOKEN_ASSIGN) { TokenType op = p->tokens[p->i].type; Advance(p); - Node right = ParseComparison(p); + Node right = ParseDot(p); Node* leftPtr = SafeMalloc(sizeof(Node)); Node* rightPtr = SafeMalloc(sizeof(Node)); @@ -521,6 +542,100 @@ node.ifStat = ret; return node; } +static Node ParseWhile(Parser* p) { + Advance(p); + + WhileNode ret; + ret.i = INFO(NODE_WHILE); + + ret.condition = NodeToHeap(ParseBinary(p)); + + Expect(p, TOKEN_DO); + Advance(p); + Expect(p, TOKEN_LINE); + Advance(p); + + ret.body = ParseBody(p, &ret.bodyLen); + Expect(p, TOKEN_END); + + Node node; + node.whileStat = ret; + return node; +} + +static Node ParseTypeDef(Parser* p) { + Advance(p); + + char* name; + Expect(p, TOKEN_IDENTIFIER); + name = NewString(p->tokens[p->i].contents); + + Advance(p); + + if (p->tokens[p->i].type == TOKEN_ASSIGN) { + Advance(p); + + TypeDefNode ret; + ret.i = INFO(NODE_TYPE_DEF); + ret.name = name; + ret.type = NodeToHeap(ParseType(p)); + + if (ret.type->i.type == NODE_PTR) { + PrintError(p->tokens[p->i].err, "Cannot use pointer for type definition"); + } + + Advance(p); + Expect(p, TOKEN_LINE); + + Node node; + node.typeDef = ret; + return node; + } + + TypeBlockNode ret; + ret.i = INFO(NODE_TYPE_BLOCK); + ret.name = name; + + if (p->tokens[p->i].type == TOKEN_UNION) { + ret.isUnion = true; + Advance(p); + } + + Expect(p, TOKEN_LINE); + Advance(p); + + ret.fields = NULL; + ret.fieldsNum = 0; + + while (p->tokens[p->i].type != TOKEN_END) { + TypeBlockField field; + + Expect(p, TOKEN_IDENTIFIER); + field.name = NewString(p->tokens[p->i].contents); + Advance(p); + + Expect(p, TOKEN_AS); + Advance(p); + + field.type = NodeToHeap(ParseType(p)); + Advance(p); + Expect(p, TOKEN_LINE); + Advance(p); + + // TODO: improve this + ++ ret.fieldsNum; + ret.fields = SafeRealloc(ret.fields, ret.fieldsNum * sizeof(TypeBlockField)); + ret.fields[ret.fieldsNum - 1] = field; + } + + Advance(p); + Expect(p, TOKEN_LINE); + + Node node; + node.typeBlock = ret; + return node; +} + static Node ParseNode(Parser* p) { switch (p->tokens[p->i].type) { case TOKEN_FUNC: @@ -528,6 +643,8 @@ case TOKEN_SUB: return ParseFuncDef(p); case TOKEN_DIM: return ParseDim(p); case TOKEN_EXTERN: return ParseExtern(p); case TOKEN_IF: return ParseIf(p); + case TOKEN_WHILE: return ParseWhile(p); + case TOKEN_TYPE: return ParseTypeDef(p); case TOKEN_IDENTIFIER: { if (p->i == p->tokenNum - 1) { PrintError(p->tokens[p->i].err, "Unexpected EOF"); @@ -586,15 +703,16 @@ printf("("); Parser_PrintNode(node->bin.left); switch (node->bin.op) { - case TOKEN_ADD: printf("+"); break; - case TOKEN_SUBTRACT: printf("-"); break; - case TOKEN_MULTIPLY: printf("*"); break; - case TOKEN_DIVIDE: printf("/"); break; + case TOKEN_ADD: printf("+"); break; + case TOKEN_SUBTRACT: printf("-"); break; + case TOKEN_MULTIPLY: printf("*"); break; + case TOKEN_DIVIDE: printf("/"); break; case TOKEN_MOD: printf("%%"); break; case TOKEN_EQUAL: printf("=="); break; - case TOKEN_LESS: printf("<"); break; - case TOKEN_GREATER: printf(">"); break; - case TOKEN_ASSIGN: printf("="); break; + case TOKEN_LESS: printf("<"); break; + case TOKEN_GREATER: printf(">"); break; + case TOKEN_ASSIGN: printf("="); break; + case TOKEN_DOT: printf("."); break; default: assert(0); } @@ -629,9 +747,8 @@ case NODE_FUNC_DEF: { PrintDec(node->funcDef.dec); for (size_t i = 0; i < node->funcDef.bodyLen; ++ i) { - printf("\t"); + printf(" "); Parser_PrintNode(&node->funcDef.body[i]); - puts(""); } puts("end"); break; @@ -680,6 +797,38 @@ puts("end"); break; } + case NODE_WHILE: { + printf("while "); + Parser_PrintNode(node->whileStat.condition); + printf(" do\n"); + + for (size_t i = 0; i < node->whileStat.bodyLen; ++ i) { + printf(" "); + Parser_PrintNode(&node->whileStat.body[i]); + } + + puts("end"); + break; + } + case NODE_TYPE_DEF: { + printf("type %s = ", node->typeDef.name); + Parser_PrintNode(node->typeDef.type); + puts(""); + break; + } + case NODE_TYPE_BLOCK: { + printf( + "type %s%s\n", node->typeBlock.name, node->typeBlock.isUnion? " union" : "" + ); + + for (size_t i = 0; i < node->typeBlock.fieldsNum; ++ i) { + printf("%s as ", node->typeBlock.fields[i].name); + Parser_PrintNode(node->typeBlock.fields[i].type); + puts(""); + } + puts("end"); + break; + } default: { printf("unknown %d\n", node->i.type); assert(0); @@ -782,6 +931,11 @@ FreeNodes(node->ifStat.elseBody, node->ifStat.elseLen); } break; } + case NODE_WHILE: { + Parser_FreeNode(node->whileStat.condition); + FreeNodes(node->whileStat.body, node->whileStat.bodyLen); + break; + } default: return; } } @@ -800,6 +954,9 @@ case NODE_DIM: return "dim"; case NODE_FUNC_CALL: return "function call"; case NODE_EXTERN: return "extern"; case NODE_IF: return "if"; + case NODE_WHILE: return "while"; + case NODE_TYPE_DEF: return "type def"; + case NODE_TYPE_BLOCK: return "type block"; default: return "???"; } } diff --git a/basic/source/parser.h b/basic/source/parser.h index 83a7a494083d44d595164b4e308c2719daba5907..afda080435be4578eba425dc8401b6b0c203504e 100644 --- a/basic/source/parser.h +++ b/basic/source/parser.h @@ -17,7 +17,10 @@ NODE_FUNC_DEF, NODE_DIM, NODE_FUNC_CALL, NODE_EXTERN, - NODE_IF + NODE_IF, + NODE_WHILE, + NODE_TYPE_DEF, + NODE_TYPE_BLOCK } NodeType; typedef struct { @@ -106,6 +109,32 @@ Node* elseBody; size_t elseLen; } IfNode; +typedef struct { + NodeInfo i; + Node* condition; + Node* body; + size_t bodyLen; +} WhileNode; + +typedef struct { + NodeInfo i; + char* name; + Node* type; +} TypeDefNode; + +typedef struct { + char* name; + Node* type; +} TypeBlockField; + +typedef struct { + NodeInfo i; + char* name; + bool isUnion; + TypeBlockField* fields; + size_t fieldsNum; +} TypeBlockNode; + union Node { NodeInfo i; IntNode integer; @@ -119,6 +148,9 @@ DimNode dim; FuncCallNode funcCall; ExternNode external; IfNode ifStat; + WhileNode whileStat; + TypeDefNode typeDef; + TypeBlockNode typeBlock; }; typedef struct { diff --git a/basic/source/semanticAnalysis.c b/basic/source/semanticAnalysis.c index dd44ad0017c195f9bd81388f228550d749f68caf..86137ff47ad93546256e5e75aeb39d198a306f45 100644 --- a/basic/source/semanticAnalysis.c +++ b/basic/source/semanticAnalysis.c @@ -103,8 +103,35 @@ return GET_PRIM("unit", 0); } +static UsedType EvalDot(Node* node, UsedType left) { + Type* leftType = State_GetTypeFromUsed(left); + + if (node->bin.right->i.type != NODE_IDENTIFIER) { + PrintError(node->i.err, "Right operand of `.` operator must be identifier"); + } + if (leftType->type != TYPE_STRUCT) { + PrintError(node->i.err, "Using `.` operator on primitive or unit type"); + } + + const char* member = node->bin.right->ident.name; + + for (size_t i = 0; i < leftType->structLen; ++ i) { + if (strcmp(leftType->structure[i].name, member) == 0) { + return leftType->structure[i].type; + } + } + + PrintError(node->i.err, "Type '%s' does not have member '%s'", leftType->name, member); + return GET_PRIM("unit", 0); +} + static UsedType EvalBinOp(Node* node) { - UsedType left = SemanticAnalysis_EvalType(node->bin.left); + UsedType left = SemanticAnalysis_EvalType(node->bin.left); + + if (node->bin.op == TOKEN_DOT) { + return EvalDot(node, left); + } + UsedType right = SemanticAnalysis_EvalType(node->bin.right); Type* leftType = State_GetTypeFromUsed(left); @@ -386,6 +413,64 @@ for (size_t i = 0; i < node->ifStat.elseLen; ++ i) { SemanticAnalysis_EvalType(&node->ifStat.elseBody[i]); } + return GET_PRIM("unit", 0); + } + case NODE_WHILE: { + Type conditionType = state.types[ + SemanticAnalysis_EvalType(node->whileStat.condition).typeIdx + ]; + + if (!State_IsInt(conditionType)) { + PrintError(node->i.err, "While condition must evaluate to an integer"); + } + + for (size_t i = 0; i < node->whileStat.bodyLen; ++ i) { + SemanticAnalysis_EvalType(&node->whileStat.body[i]); + } + + return GET_PRIM("unit", 0); + } + case NODE_TYPE_DEF: { + if (State_GetType(node->typeDef.name) != NULL) { + PrintError(node->i.err, "Type '%s' already exists", node->typeDef.name); + } + + assert(node->typeDef.type->i.type == NODE_IDENTIFIER); + + const char* fromName = node->typeDef.type->ident.name; + Type* from = State_GetType(fromName); + + if (!from) { + PrintError(node->i.err, "Type '%s' does not exist", fromName); + } + + Type newType = *from; + newType.name = NewString(node->typeDef.name); + State_AddType(newType); + + return GET_PRIM("unit", 0); + } + case NODE_TYPE_BLOCK: { + if (State_GetType(node->typeBlock.name) != NULL) { + PrintError(node->i.err, "Type '%s' already exists", node->typeBlock.name); + } + + Type newType; + newType.type = TYPE_STRUCT; + newType.name = NewString(node->typeBlock.name); + newType.size = 0; + + newType.structure = SafeMalloc(node->typeBlock.fieldsNum * sizeof(TypeField)); + newType.structLen = node->typeBlock.fieldsNum; + + for (size_t i = 0; i < node->typeBlock.fieldsNum; ++ i) { + newType.structure[i] = (TypeField) { + .name = NewString(node->typeBlock.fields[i].name), + .type = SemanticAnalysis_NodeAsUsedType(node->typeBlock.fields[i].type) + }; + } + + State_AddType(newType); return GET_PRIM("unit", 0); } default: { diff --git a/basic/source/state.c b/basic/source/state.c index ece1a8c4a3130ec1836438b4d24a396846640226..cbc1d5d22a58a42866e7bbc3fe35afe4afd1afb9 100644 --- a/basic/source/state.c +++ b/basic/source/state.c @@ -108,6 +108,12 @@ puts("TYPES"); puts("====="); for (size_t i = 0; i < state.typeNum; ++ i) { printf("- %s\n", state.types[i].name); + + if (state.types[i].type == TYPE_STRUCT) { + for (size_t j = 0; j < state.types[i].structLen; ++ j) { + printf(" - %s\n", state.types[i].structure[j].name); + } + } } puts("\n"); diff --git a/basic/source/state.h b/basic/source/state.h index 2af51b78e5775050144b5f848a98fbd3cfe54ebb..a52b2bed4cd11062a5743e1852a08a80ed514053 100644 --- a/basic/source/state.h +++ b/basic/source/state.h @@ -22,13 +22,18 @@ size_t array; // 0 if not array, contains length if not array } UsedType; typedef struct { + char* name; + UsedType type; +} TypeField; + +typedef struct { int type; char* name; size_t size; // only for "struct" types - UsedType* structure; - size_t structLen; + TypeField* structure; + size_t structLen; // only for "primitive" types int primType; diff --git a/basic/test.bas b/basic/test.bas index 1536008312bf9bc0935fe4b9119c8a2dc5e96131..3068b3bdf95fd46971f33ffeab1e095d2ecb58ac 100644 --- a/basic/test.bas +++ b/basic/test.bas @@ -1,20 +1,22 @@ 'NITRON -extern func puts(str as ptr(char)) int +extern func puts(str as ptr(char)) i32 +extern func printf(str as ptr(char), val as int) i32 -sub SayHello() - puts("Hello!") +type MyStruct + bol as int + polly as int end -SayHello() +type MyInt = int -dim a as int -a = 5 +dim manul as MyStruct -if a == 5 then - puts("a is 5") -else if a == 6 then - puts("a is 6") -else - puts("a is not 5 or 6") -end +manul.bol = 11 +manul.polly = 10 + +' should work +printf("bol: %d\n", manul.bol) + +' should also work +printf("polly: %d\n", manul.polly) diff --git a/basic/test2.bas b/basic/test2.bas new file mode 100644 index 0000000000000000000000000000000000000000..08fb2be0209cd470a4560c6a56948753682be1e5 --- /dev/null +++ b/basic/test2.bas @@ -0,0 +1 @@ +print(1+2+3+4)