started work on assignment operators
This commit is contained in:
		
							
								
								
									
										20
									
								
								AST.py
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								AST.py
									
									
									
									
									
								
							| @@ -21,6 +21,7 @@ class NodeType(Enum): | ||||
|     # Expressions | ||||
|     InfixExpression = "InfixExpression" | ||||
|     CallExpression = "CallExpression" | ||||
|     PrefixExpression = "PrefixExpression" | ||||
|  | ||||
|     # Literals | ||||
|     IntegerLiteral = "IntegerLiteral" | ||||
| @@ -221,8 +222,9 @@ class FunctionStatement(Statement): | ||||
|         } | ||||
|      | ||||
| class ReassignStatement(Statement): | ||||
|     def __init__(self, ident: Expression = None, right_value: Expression = None) -> None: | ||||
|     def __init__(self, ident: Expression = None, operator: str = "", right_value: Expression = None) -> None: | ||||
|         self.ident = ident | ||||
|         self.operator = operator | ||||
|         self.right_value = right_value | ||||
|  | ||||
|     def type(self) -> NodeType: | ||||
| @@ -232,6 +234,7 @@ class ReassignStatement(Statement): | ||||
|         return { | ||||
|             "type": self.type().value, | ||||
|             "ident": self.ident.json(), | ||||
|             "operator": self.operator, | ||||
|             "right_value": self.right_value.json() | ||||
|         } | ||||
|      | ||||
| @@ -342,4 +345,19 @@ class CallExpression(Expression): | ||||
|             "function": self.function.json(), | ||||
|             "arguments": [arg.json() for arg in self.arguments] | ||||
|         } | ||||
|      | ||||
| class PrefixExpression(Expression): | ||||
|     def __init__(self, operator: str, right_node: Expression = None) -> None: | ||||
|         self.operator = operator | ||||
|         self.right_node = right_node | ||||
|  | ||||
|     def type(self) -> NodeType: | ||||
|         return NodeType.PrefixExpression | ||||
|      | ||||
|     def json(self) -> dict: | ||||
|         return { | ||||
|             "type": self.type().value, | ||||
|             "operator": self.operator, | ||||
|             "right_node": self.right_node.json() | ||||
|         } | ||||
| # endregion | ||||
							
								
								
									
										70
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										70
									
								
								README.md
									
									
									
									
									
								
							| @@ -1,3 +1,71 @@ | ||||
| # Plasma | ||||
|  | ||||
| The Plasma programming language. | ||||
| The Plasma programming language. | ||||
|  | ||||
| # Syntax Guide | ||||
| ## Functions | ||||
| All your logic must be contained in the "main" function, which looks like this: | ||||
| ```cpp | ||||
| main = Func(): Int { | ||||
|  | ||||
| } | ||||
| ``` | ||||
| This is how you define functions. In this example, "main" is the name of the function, and `Int` is the return type. My function takes no arguments. | ||||
| If I wanted to make a function that takes arguments, it might look like this: | ||||
| ```cpp | ||||
| add = Func(number1: Int, number2: Int): Int { | ||||
| 	return number1 + number2 | ||||
| } | ||||
| ``` | ||||
| This is a function that adds two numbers together, here's the same function in Python: | ||||
| ```py | ||||
| def add(number1: int, number2: int) -> int: | ||||
| 	return number1 + number2 | ||||
| ``` | ||||
|  | ||||
| ### Calling Functions | ||||
| To call a function, you type a dollar sign (the $ symbol), then the name of the function, and then you pass any of your arguments inbetween paranthesis, like this: | ||||
| ```cpp | ||||
| add = Func(number1: Int, number2: Int): Int { | ||||
| 	return number1 + number2 | ||||
| } | ||||
| ... | ||||
| later in my code... | ||||
| ... | ||||
| $add(9, 10); | ||||
| ``` | ||||
|  | ||||
| Here's a "Hello, World!" program in Plasma: | ||||
| ```cpp | ||||
| main = Func(): Int { | ||||
| 	$print("Hello, World!\n"); | ||||
| } | ||||
| ``` | ||||
| `print` is a builtin function, it's defined in every piece of code you write. It has the same formatting as the `printf` function in C, so if I wanted to print an integer I could do it like so: | ||||
| ```cpp | ||||
| $print("%i\n", 123); | ||||
| ``` | ||||
|  | ||||
|  | ||||
| ## Variables | ||||
| To create a variable, it's as simple as: | ||||
| ```cpp | ||||
| name: Type = value; | ||||
| ``` | ||||
|  | ||||
| There are several types in Plasma, which are: `Int`, `Float`, `Bool`, `String` | ||||
|  | ||||
| Here's another example: | ||||
| ```cpp | ||||
| name: String = "bob"; | ||||
| age: Int = 23; | ||||
| ``` | ||||
|  | ||||
| To change the value of an already defined variable, you just have to provide the name, and then write an equals sign, like this: | ||||
| ```cpp | ||||
| -- defining the variable | ||||
| age: Int = 23; | ||||
|  | ||||
| -- changing it later | ||||
| age = age + 1; | ||||
| ``` | ||||
							
								
								
									
										79
									
								
								compiler.py
									
									
									
									
									
								
							
							
						
						
									
										79
									
								
								compiler.py
									
									
									
									
									
								
							| @@ -3,7 +3,7 @@ from llvmlite import ir | ||||
| from AST import Node, NodeType, Program, Expression | ||||
| from AST import ExpressionStatement, AssignmentStatement, BlockStatement, ReturnStatement, FunctionStatement, ReassignStatement, IfStatement | ||||
| from AST import WhileStatement, BreakStatement, ContinueStatement, ForStatement | ||||
| from AST import InfixExpression, CallExpression | ||||
| from AST import InfixExpression, CallExpression, PrefixExpression | ||||
| from AST import IntegerLiteral, FloatLiteral, IdentifierLiteral, BooleanLiteral, StringLiteral | ||||
| from AST import FunctionParameter | ||||
|  | ||||
| @@ -189,15 +189,56 @@ class Compiler: | ||||
|  | ||||
| 	def __visit_reassign_statement(self, node: ReassignStatement) -> None: | ||||
| 		name: str = node.ident.value | ||||
| 		operator: str = node.operator | ||||
| 		value: Expression = node.right_value | ||||
|  | ||||
| 		value, Type = self.__resolve_value(value) | ||||
| 		 | ||||
|  | ||||
| 		if self.environment.lookup(name) is None: | ||||
| 			self.errors.append(f"Identifier {name} has not been declared before it was re-assigned.") | ||||
| 		else: | ||||
| 			ptr, _ = self.environment.lookup(name) | ||||
| 			self.builder.store(value, ptr) | ||||
| 			return | ||||
|  | ||||
| 		right_value, right_type = self.__resolve_value(value) | ||||
|  | ||||
| 		var_ptr, _ = self.environment.lookup(name) | ||||
| 		orig_value = self.builder.load(var_ptr) | ||||
|  | ||||
| 		if isinstance(orig_value.type, ir.IntType) and isinstance(right_type, ir.FloatType): | ||||
| 			orig_value = self.builder.sitofp(orig_value, ir.FloatType()) | ||||
|  | ||||
| 		if isinstance(orig_value.type, ir.FloatType) and isinstance(right_type, ir.IntType): | ||||
| 			right_value = self.builder.sitofp(right_value, ir.FloatType()) | ||||
|  | ||||
| 		value = None | ||||
| 		Type = None | ||||
| 		match operator: | ||||
| 			case "=": | ||||
| 				value = right_value | ||||
| 			case "+=": | ||||
| 				if isinstance(orig_value.type, ir.IntType) and isinstance(right_type, ir.IntType): | ||||
| 					value = self.builder.add(orig_value, right_value) | ||||
| 				else: | ||||
| 					value = self.builder.fadd(orig_value, right_value) | ||||
| 			case "-=": | ||||
| 				if isinstance(orig_value.type, ir.IntType) and isinstance(right_type, ir.IntType): | ||||
| 					value = self.builder.sub(orig_value, right_value) | ||||
| 				else: | ||||
| 					value = self.builder.fsub(orig_value, right_value) | ||||
| 			case "*=": | ||||
| 				if isinstance(orig_value.type, ir.IntType) and isinstance(right_type, ir.IntType): | ||||
| 					value = self.builder.mul(orig_value, right_value) | ||||
| 				else: | ||||
| 					value = self.builder.fmul(orig_value, right_value) | ||||
| 			case "/=": | ||||
| 				if isinstance(orig_value.type, ir.IntType) and isinstance(right_type, ir.IntType): | ||||
| 					value = self.builder.sdiv(orig_value, right_value) | ||||
| 				else: | ||||
| 					value = self.builder.fdiv(orig_value, right_value) | ||||
| 			case _: | ||||
| 				print("Unsupported assignment operator.") | ||||
| 		 | ||||
| 		ptr, _ = self.environment.lookup(name) | ||||
| 		self.builder.store(value, ptr) | ||||
|  | ||||
| 	def __visit_if_statement(self, node: IfStatement) -> None: | ||||
| 		condition = node.condition | ||||
| @@ -388,6 +429,32 @@ class Compiler: | ||||
| 				ret = self.builder.call(func, args) | ||||
|  | ||||
| 		return ret, ret_type | ||||
| 	 | ||||
| 	def __visit_prefix_expression(self, node: PrefixExpression) -> tuple[ir.Value, ir.Type]: | ||||
| 		operator: str = node.operator | ||||
| 		right_node: Expression = node.right_node | ||||
|  | ||||
| 		right_value, right_type = self.__resolve_value(right_node) | ||||
|  | ||||
| 		Type = None | ||||
| 		value = None | ||||
|  | ||||
| 		if isinstance(right_type, ir.FloatType): | ||||
| 			Type = ir.FloatType | ||||
| 			match operator: | ||||
| 				case "-": | ||||
| 					value = self.builder.fmul(right_value, ir.Constant(ir.FloatType(), -1.0)) | ||||
| 				case "!": | ||||
| 					value = ir.Constant(ir.IntType(1), 0) | ||||
| 		elif isinstance(right_type, ir.IntType): | ||||
| 			Type = ir.IntType(32) | ||||
| 			match operator: | ||||
| 				case "-": | ||||
| 					value = self.builder.mul(right_value, ir.Constant(ir.IntType(32), -1)) | ||||
| 				case "!": | ||||
| 					value = self.builder.not_(right_value) | ||||
|  | ||||
| 		return value, Type | ||||
| 	# endregion | ||||
|  | ||||
| 	# endregion | ||||
| @@ -420,6 +487,8 @@ class Compiler: | ||||
| 				return self.__visit_infix_expression(node) | ||||
| 			case NodeType.CallExpression: | ||||
| 				return self.__visit_call_expression(node) | ||||
| 			case NodeType.PrefixExpression: | ||||
| 				return self.__visit_prefix_expression(node) | ||||
| 			 | ||||
| 	def __convert_string(self, string: str) -> tuple[ir.Constant, ir.ArrayType]: | ||||
| 		string = string.replace("\\n", "\n\0") | ||||
|   | ||||
| @@ -1,80 +0,0 @@ | ||||
| { | ||||
|     "type": "Program", | ||||
|     "statements": [ | ||||
|         { | ||||
|             "FunctionStatement": { | ||||
|                 "type": "FunctionStatement", | ||||
|                 "name": { | ||||
|                     "type": "IdentifierLiteral", | ||||
|                     "value": "main" | ||||
|                 }, | ||||
|                 "return_type": "Int", | ||||
|                 "parameters": [], | ||||
|                 "body": { | ||||
|                     "type": "BlockStatement", | ||||
|                     "statements": [ | ||||
|                         { | ||||
|                             "type": "ForStatement", | ||||
|                             "var_declaration": { | ||||
|                                 "type": "AssignmentStatement", | ||||
|                                 "name": { | ||||
|                                     "type": "IdentifierLiteral", | ||||
|                                     "value": "x" | ||||
|                                 }, | ||||
|                                 "value": { | ||||
|                                     "type": "IntegerLiteral", | ||||
|                                     "value": 1 | ||||
|                                 }, | ||||
|                                 "value_type": "Int" | ||||
|                             }, | ||||
|                             "condition": { | ||||
|                                 "type": "InfixExpression", | ||||
|                                 "left_node": { | ||||
|                                     "type": "IdentifierLiteral", | ||||
|                                     "value": "x" | ||||
|                                 }, | ||||
|                                 "operator": "<=", | ||||
|                                 "right_node": { | ||||
|                                     "type": "IntegerLiteral", | ||||
|                                     "value": 20 | ||||
|                                 } | ||||
|                             }, | ||||
|                             "body": { | ||||
|                                 "type": "BlockStatement", | ||||
|                                 "statements": [ | ||||
|                                     { | ||||
|                                         "type": "ExpressionStatement", | ||||
|                                         "expr": { | ||||
|                                             "type": "CallExpression", | ||||
|                                             "function": { | ||||
|                                                 "type": "IdentifierLiteral", | ||||
|                                                 "value": "print" | ||||
|                                             }, | ||||
|                                             "arguments": [ | ||||
|                                                 { | ||||
|                                                     "type": "StringLiteral", | ||||
|                                                     "value": "i = %i\\n" | ||||
|                                                 }, | ||||
|                                                 { | ||||
|                                                     "type": "IdentifierLiteral", | ||||
|                                                     "value": "x" | ||||
|                                                 } | ||||
|                                             ] | ||||
|                                         } | ||||
|                                     } | ||||
|                                 ] | ||||
|                             } | ||||
|                         }, | ||||
|                         { | ||||
|                             "type": "ReturnStatement", | ||||
|                             "return_value": { | ||||
|                                 "type": "IdentifierLiteral", | ||||
|                                 "value": "x" | ||||
|                             } | ||||
|                         } | ||||
|                     ] | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     ] | ||||
| } | ||||
							
								
								
									
										34
									
								
								debug/ir.ll
									
									
									
									
									
								
							
							
						
						
									
										34
									
								
								debug/ir.ll
									
									
									
									
									
								
							| @@ -1,34 +0,0 @@ | ||||
| ; ModuleID = "main" | ||||
| target triple = "x86_64-pc-windows-msvc" | ||||
| target datalayout = "" | ||||
|  | ||||
| declare i32 @"printf"(i8* %".1", ...) | ||||
|  | ||||
| @"true" = constant i1 1 | ||||
| @"false" = constant i1 0 | ||||
| define i32 @"main"() | ||||
| { | ||||
| main_entry: | ||||
|   %".2" = alloca i32 | ||||
|   store i32 0, i32* %".2" | ||||
|   %".4" = load i32, i32* %".2" | ||||
|   %".5" = icmp slt i32 %".4", 10 | ||||
|   br i1 %".5", label %"while_loop_entry_1", label %"while_loop_otherwise_1" | ||||
| while_loop_entry_1: | ||||
|   %".7" = load i32, i32* %".2" | ||||
|   %".8" = alloca [9 x i8]* | ||||
|   store [9 x i8]* @"__str_2", [9 x i8]** %".8" | ||||
|   %".10" = bitcast [9 x i8]* @"__str_2" to i8* | ||||
|   %".11" = call i32 (i8*, ...) @"printf"(i8* %".10", i32 %".7") | ||||
|   %".12" = load i32, i32* %".2" | ||||
|   %".13" = add i32 %".12", 1 | ||||
|   store i32 %".13", i32* %".2" | ||||
|   %".15" = load i32, i32* %".2" | ||||
|   %".16" = icmp slt i32 %".15", 10 | ||||
|   br i1 %".16", label %"while_loop_entry_1", label %"while_loop_otherwise_1" | ||||
| while_loop_otherwise_1: | ||||
|   %".18" = load i32, i32* %".2" | ||||
|   ret i32 %".18" | ||||
| } | ||||
|  | ||||
| @"__str_2" = internal constant [9 x i8] c"a = %i\0a\00\00" | ||||
							
								
								
									
										31
									
								
								lexer.py
									
									
									
									
									
								
							
							
						
						
									
										31
									
								
								lexer.py
									
									
									
									
									
								
							| @@ -84,13 +84,33 @@ class Lexer: | ||||
|  | ||||
| 		match self.current_char: | ||||
| 			case "+": | ||||
| 				tok = self.__new_token(TokenType.PLUS, self.current_char) | ||||
| 				if self.__peek_char() == "=": | ||||
| 					ch = self.current_char | ||||
| 					self.__read_char() | ||||
| 					tok = self.__new_token(TokenType.PLUS_EQ, ch + self.current_char) | ||||
| 				else: | ||||
| 					tok = self.__new_token(TokenType.PLUS, self.current_char) | ||||
| 			case "-": | ||||
| 				tok = self.__new_token(TokenType.MINUS, self.current_char) | ||||
| 				if self.__peek_char() == "=": | ||||
| 					ch = self.current_char | ||||
| 					self.__read_char() | ||||
| 					tok = self.__new_token(TokenType.MINUS_EQ, ch + self.current_char) | ||||
| 				else: | ||||
| 					tok = self.__new_token(TokenType.MINUS, self.current_char) | ||||
| 			case "*": | ||||
| 				tok = self.__new_token(TokenType.ASTERISK, self.current_char) | ||||
| 				if self.__peek_char() == "=": | ||||
| 					ch = self.current_char | ||||
| 					self.__read_char() | ||||
| 					tok = self.__new_token(TokenType.MUL_EQ, ch + self.current_char) | ||||
| 				else: | ||||
| 					tok = self.__new_token(TokenType.ASTERISK, self.current_char) | ||||
| 			case "/": | ||||
| 				tok = self.__new_token(TokenType.SLASH, self.current_char) | ||||
| 				if self.__peek_char() == "=": | ||||
| 					ch = self.current_char | ||||
| 					self.__read_char() | ||||
| 					tok = self.__new_token(TokenType.DIV_EQ, ch + self.current_char) | ||||
| 				else: | ||||
| 					tok = self.__new_token(TokenType.SLASH, self.current_char) | ||||
| 			case "^": | ||||
| 				tok = self.__new_token(TokenType.POW, self.current_char) | ||||
| 			case "%": | ||||
| @@ -126,8 +146,7 @@ class Lexer: | ||||
| 					self.__read_char() | ||||
| 					tok = self.__new_token(TokenType.NOT_EQ, ch + self.current_char) | ||||
| 				else: | ||||
| 					# TODO: handle BANG | ||||
| 					tok = self.__new_token(TokenType.ILLEGAL, self.current_char) | ||||
| 					tok = self.__new_token(TokenType.BANG, self.current_char) | ||||
| 			case "(": | ||||
| 				tok = self.__new_token(TokenType.LPAREN, self.current_char) | ||||
| 			case ")": | ||||
|   | ||||
| @@ -23,6 +23,10 @@ class TokenType(Enum): | ||||
|  | ||||
| 	# Assignment symbols | ||||
| 	EQ = "EQ" | ||||
| 	PLUS_EQ = "PLUS_EQ" | ||||
| 	MINUS_EQ = "MINUS_EQ" | ||||
| 	MUL_EQ = "MUL_EQ" | ||||
| 	DIV_EQ = "DIV_EQ" | ||||
|  | ||||
| 	# Comparison symbols | ||||
| 	LT = "<" | ||||
| @@ -43,6 +47,7 @@ class TokenType(Enum): | ||||
| 	SEMICOLON = "SEMICOLON" | ||||
| 	COMMA = "COMMA" | ||||
| 	DOLLARSIGN = "DOLLARSIGN" | ||||
| 	BANG = "BANG" | ||||
|  | ||||
| 	# Keywords | ||||
| 	RETURN = "RETURN" | ||||
|   | ||||
							
								
								
									
										2
									
								
								main.py
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								main.py
									
									
									
									
									
								
							| @@ -10,7 +10,7 @@ import llvmlite.binding as llvm | ||||
| from ctypes import CFUNCTYPE, c_int, c_float | ||||
|  | ||||
| LEXER_DEBUG: bool = False | ||||
| PARSER_DEBUG: bool = False | ||||
| PARSER_DEBUG: bool = True | ||||
| COMPILER_DEBUG: bool = False | ||||
| RUN_CODE: bool = True | ||||
|  | ||||
|   | ||||
| @@ -5,7 +5,8 @@ from enum import Enum, auto | ||||
|  | ||||
| from AST import Statement, Expression, Program | ||||
| from AST import ExpressionStatement, AssignmentStatement, FunctionStatement, ReturnStatement, BlockStatement, ReassignStatement, IfStatement, WhileStatement | ||||
| from AST import InfixExpression, CallExpression, BreakStatement, ContinueStatement, ForStatement | ||||
| from AST import InfixExpression, CallExpression, PrefixExpression | ||||
| from AST import BreakStatement, ContinueStatement, ForStatement | ||||
| from AST import IntegerLiteral, FloatLiteral, IdentifierLiteral, BooleanLiteral, StringLiteral | ||||
| from AST import FunctionParameter | ||||
|  | ||||
| @@ -57,7 +58,10 @@ class Parser: | ||||
|  | ||||
| 			TokenType.STRING: self.__parse_string_literal, | ||||
|  | ||||
| 			TokenType.DOLLARSIGN: self.__parse_call_expression | ||||
| 			TokenType.DOLLARSIGN: self.__parse_call_expression, | ||||
|  | ||||
| 			TokenType.MINUS: self.__parse_prefix_expression, | ||||
| 			TokenType.BANG: self.__parse_prefix_expression, | ||||
| 		}  | ||||
| 		self.infix_parse_functions: dict[Token, Callable] = { # 5 + 5 | ||||
| 			TokenType.PLUS: self.__parse_infix_expression, | ||||
| @@ -89,6 +93,16 @@ class Parser: | ||||
| 	def __peek_token_is(self, tt: TokenType) -> bool: | ||||
| 		return self.peek_token.type == tt | ||||
| 	 | ||||
| 	def __peek_token_is_assignment(self) -> bool: | ||||
| 		assignment_operators: list[TokenType] = [ | ||||
| 			TokenType.EQ, | ||||
| 			TokenType.PLUS_EQ, | ||||
| 			TokenType.MINUS_EQ, | ||||
| 			TokenType.MUL_EQ, | ||||
| 			TokenType.DIV_EQ, | ||||
| 		] | ||||
| 		return self.peek_token.type in assignment_operators | ||||
|  | ||||
| 	def __expect_peek(self, tt: TokenType) -> bool: | ||||
| 		if self.__peek_token_is(tt): | ||||
| 			self.__next_token() | ||||
| @@ -161,12 +175,13 @@ class Parser: | ||||
| 		# x: Int = 10; | ||||
| 		stmt: AssignmentStatement = AssignmentStatement(name=IdentifierLiteral(self.current_token.literal)) | ||||
|  | ||||
| 		if self.__peek_token_is(TokenType.EQ): # function definition | ||||
| 		if self.__peek_token_is_assignment(): # function definition | ||||
| 			# x = Func(): Int { return 10; } | ||||
|  | ||||
| 			 | ||||
| 			self.__next_token() | ||||
|  | ||||
| 			if self.__peek_token_is(TokenType.TYPE): | ||||
| 			if self.__current_token_is(TokenType.EQ) and self.__peek_token_is(TokenType.TYPE): | ||||
| 				func_stmt: FunctionStatement = FunctionStatement(name=stmt.name) | ||||
| 				 | ||||
| 				if self.peek_token.literal != "Func": | ||||
| @@ -197,9 +212,12 @@ class Parser: | ||||
| 			else: # reassignment statement | ||||
| 				assign_stmt: ReassignStatement = ReassignStatement() | ||||
|  | ||||
|  | ||||
| 				assign_stmt.operator = self.current_token.literal | ||||
| 				assign_stmt.ident = stmt.name | ||||
|  | ||||
| 				self.__next_token() | ||||
|  | ||||
| 				assign_stmt.ident = stmt.name | ||||
| 				assign_stmt.right_value = self.__parse_expression(PrecedenceType.P_LOWEST) | ||||
|  | ||||
| 				 | ||||
| @@ -430,6 +448,15 @@ class Parser: | ||||
| 			return None | ||||
|  | ||||
| 		return e_list | ||||
| 	 | ||||
| 	def __parse_prefix_expression(self) -> PrefixExpression: | ||||
| 		prefix_expr: PrefixExpression = PrefixExpression(operator=self.current_token.literal) | ||||
|  | ||||
| 		self.__next_token() | ||||
|  | ||||
| 		prefix_expr.right_node = self.__parse_expression(PrecedenceType.P_PREFIX) | ||||
|  | ||||
| 		return prefix_expr | ||||
| 	# endregion | ||||
|  | ||||
| 	# region Prefix Methods | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| main = Func(): Int { | ||||
| 	for (x: Int = 1; x <= 20; x = x + 1;) { | ||||
| 		$print("i = %i\n", x) | ||||
| 	} | ||||
| 	a: Int = 10; | ||||
|  | ||||
| 	return x; | ||||
| 	a += 1; | ||||
|  | ||||
| 	return a; | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 SpookyDervish
					SpookyDervish