neuron-lang 1.0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
neuron/__init__.py ADDED
@@ -0,0 +1,18 @@
1
+ """
2
+ Neuron Programming Language
3
+ ===========================
4
+ A Python-like, OOP-based programming language purpose-built for
5
+ Artificial Intelligence development.
6
+
7
+ File extension: .nl
8
+ Website: https://neuron-lang.org (coming soon)
9
+
10
+ Keywords: do, give, show, ask, when, orwhen, otherwise, each,
11
+ repeat, grab, entity, brain, me, create, yes, no,
12
+ nothing, also, either, nah, safe, rescue, stop, skip,
13
+ quick, within, drop, ensure, emit, shared, from, upto
14
+ """
15
+
16
+ __version__ = "1.0.1"
17
+ __author__ = "Neuron Language Team"
18
+ __license__ = "MIT"
neuron/ast_nodes.py ADDED
@@ -0,0 +1,432 @@
1
+ """
2
+ Neuron AST Node Definitions
3
+ ============================
4
+ All Abstract Syntax Tree node types for the Neuron language.
5
+ Each node carries source location info for error reporting.
6
+ """
7
+
8
+
9
+ class ASTNode:
10
+ """Base class for all AST nodes."""
11
+
12
+ def __init__(self, line=None, column=None):
13
+ self.line = line
14
+ self.column = column
15
+
16
+ def accept(self, visitor):
17
+ method_name = f"visit_{type(self).__name__}"
18
+ visitor_method = getattr(visitor, method_name, None)
19
+ if visitor_method:
20
+ return visitor_method(self)
21
+ return visitor.generic_visit(self)
22
+
23
+
24
+ # ===== PROGRAM =====
25
+
26
+ class Program(ASTNode):
27
+ """Root node: a list of statements."""
28
+
29
+ def __init__(self, statements, line=None, column=None):
30
+ super().__init__(line, column)
31
+ self.statements = statements
32
+
33
+
34
+ # ===== STATEMENTS =====
35
+
36
+ class ExpressionStatement(ASTNode):
37
+ """A standalone expression used as a statement."""
38
+
39
+ def __init__(self, expression, line=None, column=None):
40
+ super().__init__(line, column)
41
+ self.expression = expression
42
+
43
+
44
+ class Assignment(ASTNode):
45
+ """Variable assignment: x = expr"""
46
+
47
+ def __init__(self, target, value, line=None, column=None):
48
+ super().__init__(line, column)
49
+ self.target = target
50
+ self.value = value
51
+
52
+
53
+ class TensorType(ASTNode):
54
+ """A statically declared tensor shape, such as tensor[32, 8]."""
55
+
56
+ def __init__(self, dimensions, line=None, column=None):
57
+ super().__init__(line, column)
58
+ self.dimensions = dimensions
59
+
60
+
61
+ class TypedAssignment(ASTNode):
62
+ """A variable assignment with a declared type."""
63
+
64
+ def __init__(self, target, type_node, value, line=None, column=None):
65
+ super().__init__(line, column)
66
+ self.target = target
67
+ self.type_node = type_node
68
+ self.value = value
69
+
70
+
71
+ class AugmentedAssignment(ASTNode):
72
+ """Augmented assignment: x += expr, x -= expr, etc."""
73
+
74
+ def __init__(self, target, op, value, line=None, column=None):
75
+ super().__init__(line, column)
76
+ self.target = target
77
+ self.op = op # '+', '-', '*', '/'
78
+ self.value = value
79
+
80
+
81
+ class MultiAssignment(ASTNode):
82
+ """Multiple assignment: a, b = expr1, expr2"""
83
+
84
+ def __init__(self, targets, values, line=None, column=None):
85
+ super().__init__(line, column)
86
+ self.targets = targets
87
+ self.values = values
88
+
89
+
90
+ class FunctionDef(ASTNode):
91
+ """Function definition: do name(params): body"""
92
+
93
+ def __init__(self, name, params, defaults, body, line=None, column=None):
94
+ super().__init__(line, column)
95
+ self.name = name
96
+ self.params = params # List of parameter names
97
+ self.defaults = defaults # Dict of param_name -> default_value_expr
98
+ self.body = body # List of statements
99
+
100
+
101
+ class EntityDef(ASTNode):
102
+ """Entity (class) definition: entity Name [from Parent]: body"""
103
+
104
+ def __init__(self, name, parent, body, line=None, column=None):
105
+ super().__init__(line, column)
106
+ self.name = name
107
+ self.parent = parent # Parent class name (string) or None
108
+ self.body = body # List of statements (methods, assignments)
109
+
110
+
111
+ class BrainDef(ASTNode):
112
+ """Brain (AI model) definition: brain Name [from Parent]: body"""
113
+
114
+ def __init__(self, name, parent, body, line=None, column=None):
115
+ super().__init__(line, column)
116
+ self.name = name
117
+ self.parent = parent
118
+ self.body = body
119
+
120
+
121
+ class ReturnStatement(ASTNode):
122
+ """Return statement: give expr"""
123
+
124
+ def __init__(self, value=None, line=None, column=None):
125
+ super().__init__(line, column)
126
+ self.value = value
127
+
128
+
129
+ class IfStatement(ASTNode):
130
+ """If statement: when condition: body [orwhen: ...] [otherwise: ...]"""
131
+
132
+ def __init__(self, condition, body, elif_clauses=None, else_body=None, line=None, column=None):
133
+ super().__init__(line, column)
134
+ self.condition = condition
135
+ self.body = body
136
+ self.elif_clauses = elif_clauses or [] # List of (condition, body) tuples
137
+ self.else_body = else_body # List of statements or None
138
+
139
+
140
+ class WhileLoop(ASTNode):
141
+ """While loop: repeat condition: body"""
142
+
143
+ def __init__(self, condition, body, line=None, column=None):
144
+ super().__init__(line, column)
145
+ self.condition = condition
146
+ self.body = body
147
+
148
+
149
+ class ForLoop(ASTNode):
150
+ """For loop: each var within iterable: body"""
151
+
152
+ def __init__(self, variable, iterable, body, line=None, column=None):
153
+ super().__init__(line, column)
154
+ self.variable = variable # Variable name (string)
155
+ self.iterable = iterable # Expression
156
+ self.body = body
157
+
158
+
159
+ class BreakStatement(ASTNode):
160
+ """Break: stop"""
161
+ pass
162
+
163
+
164
+ class ContinueStatement(ASTNode):
165
+ """Continue: skip"""
166
+ pass
167
+
168
+
169
+ class PassStatement(ASTNode):
170
+ """Pass/no-op: ..."""
171
+ pass
172
+
173
+
174
+ class TryCatch(ASTNode):
175
+ """Try/catch: safe: body rescue ErrorType as name: handler"""
176
+
177
+ def __init__(self, body, rescue_clauses=None, line=None, column=None):
178
+ super().__init__(line, column)
179
+ self.body = body
180
+ self.rescue_clauses = rescue_clauses or []
181
+ # Each clause: (error_type_name, alias_name, handler_body)
182
+
183
+
184
+ class GrabStatement(ASTNode):
185
+ """Import: grab module_name"""
186
+
187
+ def __init__(self, module_name, alias=None, items=None, line=None, column=None):
188
+ super().__init__(line, column)
189
+ self.module_name = module_name
190
+ self.alias = alias # grab module as alias
191
+ self.items = items # grab item from module
192
+
193
+
194
+ class DropStatement(ASTNode):
195
+ """Delete: drop variable"""
196
+
197
+ def __init__(self, target, line=None, column=None):
198
+ super().__init__(line, column)
199
+ self.target = target
200
+
201
+
202
+ class EnsureStatement(ASTNode):
203
+ """Assert: ensure condition, message"""
204
+
205
+ def __init__(self, condition, message=None, line=None, column=None):
206
+ super().__init__(line, column)
207
+ self.condition = condition
208
+ self.message = message
209
+
210
+
211
+ class EmitStatement(ASTNode):
212
+ """Yield: emit value"""
213
+
214
+ def __init__(self, value=None, line=None, column=None):
215
+ super().__init__(line, column)
216
+ self.value = value
217
+
218
+
219
+ class SharedStatement(ASTNode):
220
+ """Global: shared var_name"""
221
+
222
+ def __init__(self, names, line=None, column=None):
223
+ super().__init__(line, column)
224
+ self.names = names # List of variable names
225
+
226
+
227
+ # ===== EXPRESSIONS =====
228
+
229
+ class NumberLiteral(ASTNode):
230
+ """Numeric literal: 42, 3.14"""
231
+
232
+ def __init__(self, value, line=None, column=None):
233
+ super().__init__(line, column)
234
+ self.value = value
235
+
236
+
237
+ class StringLiteral(ASTNode):
238
+ """String literal: "hello" """
239
+
240
+ def __init__(self, value, line=None, column=None):
241
+ super().__init__(line, column)
242
+ self.value = value
243
+
244
+
245
+ class FStringLiteral(ASTNode):
246
+ """Interpolated string: "hello {name}" """
247
+
248
+ def __init__(self, parts, line=None, column=None):
249
+ super().__init__(line, column)
250
+ self.parts = parts # List of (type, value) where type is 'text' or 'expr'
251
+
252
+
253
+ class BooleanLiteral(ASTNode):
254
+ """Boolean literal: yes, no"""
255
+
256
+ def __init__(self, value, line=None, column=None):
257
+ super().__init__(line, column)
258
+ self.value = value
259
+
260
+
261
+ class NothingLiteral(ASTNode):
262
+ """Nothing literal: nothing"""
263
+
264
+ def __init__(self, line=None, column=None):
265
+ super().__init__(line, column)
266
+ self.value = None
267
+
268
+
269
+ class ListLiteral(ASTNode):
270
+ """List literal: [1, 2, 3]"""
271
+
272
+ def __init__(self, elements, line=None, column=None):
273
+ super().__init__(line, column)
274
+ self.elements = elements
275
+
276
+
277
+ class DictLiteral(ASTNode):
278
+ """Dict literal: {key: value, ...}"""
279
+
280
+ def __init__(self, pairs, line=None, column=None):
281
+ super().__init__(line, column)
282
+ self.pairs = pairs # List of (key_expr, value_expr)
283
+
284
+
285
+ class TupleLiteral(ASTNode):
286
+ """Tuple literal: (1, 2, 3)"""
287
+
288
+ def __init__(self, elements, line=None, column=None):
289
+ super().__init__(line, column)
290
+ self.elements = elements
291
+
292
+
293
+ class Identifier(ASTNode):
294
+ """Variable reference: x"""
295
+
296
+ def __init__(self, name, line=None, column=None):
297
+ super().__init__(line, column)
298
+ self.name = name
299
+
300
+
301
+ class MeExpression(ASTNode):
302
+ """Self reference: me"""
303
+
304
+ def __init__(self, line=None, column=None):
305
+ super().__init__(line, column)
306
+
307
+
308
+ class BinaryOp(ASTNode):
309
+ """Binary operation: a + b, a * b, etc."""
310
+
311
+ def __init__(self, left, op, right, line=None, column=None):
312
+ super().__init__(line, column)
313
+ self.left = left
314
+ self.op = op # '+', '-', '*', '/', '//', '%', '**'
315
+ self.right = right
316
+
317
+
318
+ class UnaryOp(ASTNode):
319
+ """Unary operation: -x, nah x"""
320
+
321
+ def __init__(self, op, operand, line=None, column=None):
322
+ super().__init__(line, column)
323
+ self.op = op # '-', 'nah'
324
+ self.operand = operand
325
+
326
+
327
+ class ComparisonOp(ASTNode):
328
+ """Comparison: a == b, a < b, etc."""
329
+
330
+ def __init__(self, left, op, right, line=None, column=None):
331
+ super().__init__(line, column)
332
+ self.left = left
333
+ self.op = op # '==', '!=', '<', '>', '<=', '>='
334
+ self.right = right
335
+
336
+
337
+ class LogicalOp(ASTNode):
338
+ """Logical operation: a also b, a either b"""
339
+
340
+ def __init__(self, left, op, right, line=None, column=None):
341
+ super().__init__(line, column)
342
+ self.left = left
343
+ self.op = op # 'also', 'either'
344
+ self.right = right
345
+
346
+
347
+ class FunctionCall(ASTNode):
348
+ """Function call: name(args)"""
349
+
350
+ def __init__(self, callee, args, kwargs=None, line=None, column=None):
351
+ super().__init__(line, column)
352
+ self.callee = callee # Expression (Identifier, PropertyAccess, etc.)
353
+ self.args = args # List of expressions
354
+ self.kwargs = kwargs or {} # Dict of name -> expression
355
+
356
+
357
+ class PropertyAccess(ASTNode):
358
+ """Property/method access: obj.prop"""
359
+
360
+ def __init__(self, object, property, line=None, column=None):
361
+ super().__init__(line, column)
362
+ self.object = object
363
+ self.property = property # String
364
+
365
+
366
+ class IndexAccess(ASTNode):
367
+ """Index access: obj[index]"""
368
+
369
+ def __init__(self, object, index, line=None, column=None):
370
+ super().__init__(line, column)
371
+ self.object = object
372
+ self.index = index
373
+
374
+
375
+ class SliceAccess(ASTNode):
376
+ """Slice access: obj[start:end:step]"""
377
+
378
+ def __init__(self, object, start, end, step=None, line=None, column=None):
379
+ super().__init__(line, column)
380
+ self.object = object
381
+ self.start = start
382
+ self.end = end
383
+ self.step = step
384
+
385
+
386
+ class PipelineOp(ASTNode):
387
+ """Pipeline: expr |> func"""
388
+
389
+ def __init__(self, left, right, line=None, column=None):
390
+ super().__init__(line, column)
391
+ self.left = left
392
+ self.right = right # Function call or identifier
393
+
394
+
395
+ class QuickFunction(ASTNode):
396
+ """Lambda: quick(params): expr"""
397
+
398
+ def __init__(self, params, body, line=None, column=None):
399
+ super().__init__(line, column)
400
+ self.params = params
401
+ self.body = body # Single expression
402
+
403
+
404
+ class ListComprehension(ASTNode):
405
+ """List comprehension: [expr each var within iterable when condition]"""
406
+
407
+ def __init__(self, expression, variable, iterable, condition=None, line=None, column=None):
408
+ super().__init__(line, column)
409
+ self.expression = expression
410
+ self.variable = variable
411
+ self.iterable = iterable
412
+ self.condition = condition
413
+
414
+
415
+ class AttributeAssignment(ASTNode):
416
+ """Attribute assignment: obj.attr = value"""
417
+
418
+ def __init__(self, object, attribute, value, line=None, column=None):
419
+ super().__init__(line, column)
420
+ self.object = object
421
+ self.attribute = attribute
422
+ self.value = value
423
+
424
+
425
+ class IndexAssignment(ASTNode):
426
+ """Index assignment: obj[idx] = value"""
427
+
428
+ def __init__(self, object, index, value, line=None, column=None):
429
+ super().__init__(line, column)
430
+ self.object = object
431
+ self.index = index
432
+ self.value = value
neuron/compiler.py ADDED
@@ -0,0 +1,198 @@
1
+ """
2
+ Neuron Bytecode Compiler
3
+ ========================
4
+ Compiles AST to bytecode and provides a VM for execution.
5
+ """
6
+
7
+ import struct
8
+ import pickle
9
+ import os
10
+ from enum import IntEnum, auto
11
+
12
+ from neuron import ast_nodes as ast
13
+ from neuron.lexer import Lexer
14
+ from neuron.parser import Parser
15
+ from neuron.semantic import StaticAnalyzer
16
+
17
+
18
+ class OpCode(IntEnum):
19
+ LOAD_CONST = 0
20
+ LOAD_VAR = 1
21
+ STORE_VAR = 2
22
+ LOAD_ATTR = 3
23
+ STORE_ATTR = 4
24
+ BINARY_ADD = 10
25
+ BINARY_SUB = 11
26
+ BINARY_MUL = 12
27
+ BINARY_DIV = 13
28
+ BINARY_MOD = 14
29
+ BINARY_POW = 15
30
+ BINARY_FLOORDIV = 16
31
+ COMPARE_EQ = 20
32
+ COMPARE_NE = 21
33
+ COMPARE_LT = 22
34
+ COMPARE_GT = 23
35
+ COMPARE_LE = 24
36
+ COMPARE_GE = 25
37
+ COMPARE_IN = 26
38
+ UNARY_NEG = 30
39
+ UNARY_NOT = 31
40
+ JUMP = 40
41
+ JUMP_IF_FALSE = 41
42
+ JUMP_IF_TRUE = 42
43
+ CALL_FUNCTION = 50
44
+ RETURN_VALUE = 51
45
+ MAKE_FUNCTION = 52
46
+ MAKE_LIST = 53
47
+ MAKE_DICT = 54
48
+ GET_INDEX = 55
49
+ SET_INDEX = 56
50
+ POP_TOP = 60
51
+ DUP_TOP = 61
52
+ BUILD_CLASS = 62
53
+ PIPE = 63
54
+ IMPORT = 64
55
+ PRINT = 65
56
+ NOP = 99
57
+ HALT = 100
58
+
59
+
60
+ class BytecodeChunk:
61
+ """A compiled chunk of bytecode."""
62
+ def __init__(self, name="<module>"):
63
+ self.name = name
64
+ self.code = [] # List of (opcode, operand) tuples
65
+ self.constants = [] # Constant pool
66
+ self.names = [] # Variable name pool
67
+ self.line_map = {} # instruction_index -> source_line
68
+
69
+ def emit(self, opcode, operand=0, line=0):
70
+ idx = len(self.code)
71
+ self.code.append((opcode, operand))
72
+ self.line_map[idx] = line
73
+ return idx
74
+
75
+ def add_constant(self, value):
76
+ if value in self.constants:
77
+ return self.constants.index(value)
78
+ self.constants.append(value)
79
+ return len(self.constants) - 1
80
+
81
+ def add_name(self, name):
82
+ if name in self.names:
83
+ return self.names.index(name)
84
+ self.names.append(name)
85
+ return len(self.names) - 1
86
+
87
+ def patch_jump(self, offset, target=None):
88
+ """Patch a jump instruction's target."""
89
+ if target is None:
90
+ target = len(self.code)
91
+ opcode, _ = self.code[offset]
92
+ self.code[offset] = (opcode, target)
93
+
94
+
95
+ class Compiler:
96
+ """Compiles Neuron AST to bytecode."""
97
+
98
+ def compile_file(self, input_path, output_path=None):
99
+ with open(input_path, 'r', encoding='utf-8') as f:
100
+ source = f.read()
101
+
102
+ chunk = self.compile_source(source, input_path)
103
+
104
+ if output_path is None:
105
+ output_path = input_path.replace('.nl', '.nlc')
106
+
107
+ with open(output_path, 'wb') as f:
108
+ pickle.dump(chunk, f)
109
+
110
+ return chunk
111
+
112
+ def compile_source(self, source, filename="<stdin>"):
113
+ lexer = Lexer(source, filename)
114
+ tokens = lexer.tokenize()
115
+ parser = Parser(tokens, source, filename)
116
+ program = parser.parse()
117
+ StaticAnalyzer(source, filename).analyze(program)
118
+
119
+ chunk = BytecodeChunk(filename)
120
+ self._compile_node(program, chunk)
121
+ chunk.emit(OpCode.HALT)
122
+ return chunk
123
+
124
+ def _compile_node(self, node, chunk):
125
+ method = f"_compile_{type(node).__name__}"
126
+ compiler = getattr(self, method, None)
127
+ if compiler:
128
+ return compiler(node, chunk)
129
+ # Fallback: skip unknown nodes
130
+ return
131
+
132
+ def _compile_Program(self, node, chunk):
133
+ for stmt in node.statements:
134
+ self._compile_node(stmt, chunk)
135
+
136
+ def _compile_NumberLiteral(self, node, chunk):
137
+ idx = chunk.add_constant(node.value)
138
+ chunk.emit(OpCode.LOAD_CONST, idx, node.line)
139
+
140
+ def _compile_StringLiteral(self, node, chunk):
141
+ idx = chunk.add_constant(node.value)
142
+ chunk.emit(OpCode.LOAD_CONST, idx, node.line)
143
+
144
+ def _compile_BooleanLiteral(self, node, chunk):
145
+ idx = chunk.add_constant(node.value)
146
+ chunk.emit(OpCode.LOAD_CONST, idx, node.line)
147
+
148
+ def _compile_NothingLiteral(self, node, chunk):
149
+ idx = chunk.add_constant(None)
150
+ chunk.emit(OpCode.LOAD_CONST, idx, node.line)
151
+
152
+ def _compile_Identifier(self, node, chunk):
153
+ idx = chunk.add_name(node.name)
154
+ chunk.emit(OpCode.LOAD_VAR, idx, node.line)
155
+
156
+ def _compile_Assignment(self, node, chunk):
157
+ self._compile_node(node.value, chunk)
158
+ idx = chunk.add_name(node.target)
159
+ chunk.emit(OpCode.STORE_VAR, idx, node.line)
160
+
161
+ def _compile_TypedAssignment(self, node, chunk):
162
+ self._compile_node(node.value, chunk)
163
+ idx = chunk.add_name(node.target)
164
+ chunk.emit(OpCode.STORE_VAR, idx, node.line)
165
+
166
+ def _compile_ExpressionStatement(self, node, chunk):
167
+ self._compile_node(node.expression, chunk)
168
+ chunk.emit(OpCode.POP_TOP)
169
+
170
+ def _compile_BinaryOp(self, node, chunk):
171
+ self._compile_node(node.left, chunk)
172
+ self._compile_node(node.right, chunk)
173
+ op_map = {
174
+ '+': OpCode.BINARY_ADD, '-': OpCode.BINARY_SUB,
175
+ '*': OpCode.BINARY_MUL, '/': OpCode.BINARY_DIV,
176
+ '%': OpCode.BINARY_MOD, '**': OpCode.BINARY_POW,
177
+ '//': OpCode.BINARY_FLOORDIV,
178
+ }
179
+ chunk.emit(op_map[node.op], 0, node.line)
180
+
181
+ def _compile_ComparisonOp(self, node, chunk):
182
+ self._compile_node(node.left, chunk)
183
+ self._compile_node(node.right, chunk)
184
+ op_map = {
185
+ '==': OpCode.COMPARE_EQ, '!=': OpCode.COMPARE_NE,
186
+ '<': OpCode.COMPARE_LT, '>': OpCode.COMPARE_GT,
187
+ '<=': OpCode.COMPARE_LE, '>=': OpCode.COMPARE_GE,
188
+ 'within': OpCode.COMPARE_IN,
189
+ }
190
+ chunk.emit(op_map[node.op], 0, node.line)
191
+
192
+ def _compile_ReturnStatement(self, node, chunk):
193
+ if node.value:
194
+ self._compile_node(node.value, chunk)
195
+ else:
196
+ idx = chunk.add_constant(None)
197
+ chunk.emit(OpCode.LOAD_CONST, idx)
198
+ chunk.emit(OpCode.RETURN_VALUE, 0, node.line)