IncludeCPP 4.3.0__py3-none-any.whl → 4.6.0__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.
- includecpp/CHANGELOG.md +22 -0
- includecpp/__init__.py +1 -1
- includecpp/__init__.pyi +1 -4
- includecpp/cli/commands.py +1218 -25
- includecpp/core/cpp_api_extensions.pyi +204 -200
- includecpp/core/cssl/__init__.py +317 -0
- includecpp/core/cssl/cpp/build/api.pyd +0 -0
- includecpp/core/cssl/cpp/build/cssl_core.pyi +323 -0
- includecpp/core/cssl/cpp/build/libgcc_s_seh-1.dll +0 -0
- includecpp/core/cssl/cpp/build/libstdc++-6.dll +0 -0
- includecpp/core/cssl/cpp/build/libwinpthread-1.dll +0 -0
- includecpp/core/cssl/cpp/cssl_core.cp +108 -0
- includecpp/core/cssl/cpp/cssl_lexer.hpp +280 -0
- includecpp/core/cssl/cssl_builtins.py +142 -27
- includecpp/core/cssl/cssl_compiler.py +448 -0
- includecpp/core/cssl/cssl_optimizer.py +833 -0
- includecpp/core/cssl/cssl_parser.py +433 -38
- includecpp/core/cssl/cssl_runtime.py +294 -15
- includecpp/core/cssl/cssl_syntax.py +17 -0
- includecpp/core/cssl/cssl_types.py +143 -11
- includecpp/core/cssl_bridge.py +39 -2
- includecpp/generator/parser.cpp +38 -14
- includecpp/vscode/cssl/package.json +15 -0
- includecpp/vscode/cssl/syntaxes/cssl.tmLanguage.json +96 -0
- {includecpp-4.3.0.dist-info → includecpp-4.6.0.dist-info}/METADATA +1 -1
- {includecpp-4.3.0.dist-info → includecpp-4.6.0.dist-info}/RECORD +30 -21
- {includecpp-4.3.0.dist-info → includecpp-4.6.0.dist-info}/WHEEL +0 -0
- {includecpp-4.3.0.dist-info → includecpp-4.6.0.dist-info}/entry_points.txt +0 -0
- {includecpp-4.3.0.dist-info → includecpp-4.6.0.dist-info}/licenses/LICENSE +0 -0
- {includecpp-4.3.0.dist-info → includecpp-4.6.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
SOURCE(include/cssl_core.cpp) cssl_core
|
|
2
|
+
|
|
3
|
+
PUBLIC(
|
|
4
|
+
// Full Interpreter - Main Entry Point
|
|
5
|
+
cssl_core FUNC(run_cssl)
|
|
6
|
+
cssl_core FUNC(version)
|
|
7
|
+
cssl_core FUNC(is_keyword)
|
|
8
|
+
|
|
9
|
+
// Lexer & Token Classes
|
|
10
|
+
cssl_core CLASS(Lexer) {
|
|
11
|
+
CONSTRUCTOR(const std::string&)
|
|
12
|
+
METHOD(tokenize)
|
|
13
|
+
}
|
|
14
|
+
cssl_core CLASS(Token) {
|
|
15
|
+
CONSTRUCTOR()
|
|
16
|
+
CONSTRUCTOR(int, int, int)
|
|
17
|
+
CONSTRUCTOR(int, const std::string&, int, int)
|
|
18
|
+
CONSTRUCTOR(int, double, int, int)
|
|
19
|
+
CONSTRUCTOR(int, bool, int, int)
|
|
20
|
+
FIELD(type)
|
|
21
|
+
FIELD(str_value)
|
|
22
|
+
FIELD(num_value)
|
|
23
|
+
FIELD(bool_value)
|
|
24
|
+
FIELD(value_type)
|
|
25
|
+
FIELD(line)
|
|
26
|
+
FIELD(column)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Full Interpreter Class
|
|
30
|
+
cssl_core CLASS(Interpreter) {
|
|
31
|
+
CONSTRUCTOR()
|
|
32
|
+
METHOD(run)
|
|
33
|
+
METHOD(run_string)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Value Class (for advanced usage)
|
|
37
|
+
cssl_core CLASS(Value) {
|
|
38
|
+
CONSTRUCTOR()
|
|
39
|
+
CONSTRUCTOR(bool)
|
|
40
|
+
CONSTRUCTOR(int64_t)
|
|
41
|
+
CONSTRUCTOR(double)
|
|
42
|
+
CONSTRUCTOR(const std::string&)
|
|
43
|
+
METHOD_CONST(as_bool)
|
|
44
|
+
METHOD_CONST(as_float)
|
|
45
|
+
METHOD_CONST(as_int)
|
|
46
|
+
METHOD_CONST(as_string)
|
|
47
|
+
METHOD_CONST(get_type)
|
|
48
|
+
METHOD_CONST(is_bool)
|
|
49
|
+
METHOD_CONST(is_dict)
|
|
50
|
+
METHOD_CONST(is_float)
|
|
51
|
+
METHOD_CONST(is_int)
|
|
52
|
+
METHOD_CONST(is_list)
|
|
53
|
+
METHOD_CONST(is_null)
|
|
54
|
+
METHOD_CONST(is_number)
|
|
55
|
+
METHOD_CONST(is_string)
|
|
56
|
+
METHOD_CONST(to_bool)
|
|
57
|
+
METHOD_CONST(to_string)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// String Operations
|
|
61
|
+
cssl_core FUNC(str_concat)
|
|
62
|
+
cssl_core FUNC(str_contains)
|
|
63
|
+
cssl_core FUNC(str_join)
|
|
64
|
+
cssl_core FUNC(str_lower)
|
|
65
|
+
cssl_core FUNC(str_replace)
|
|
66
|
+
cssl_core FUNC(str_split)
|
|
67
|
+
cssl_core FUNC(str_trim)
|
|
68
|
+
cssl_core FUNC(str_upper)
|
|
69
|
+
cssl_core FUNC(str_reverse)
|
|
70
|
+
cssl_core FUNC(str_len)
|
|
71
|
+
cssl_core FUNC(str_repeat)
|
|
72
|
+
cssl_core FUNC(str_startswith)
|
|
73
|
+
cssl_core FUNC(str_endswith)
|
|
74
|
+
cssl_core FUNC(str_indexof)
|
|
75
|
+
cssl_core FUNC(str_substr)
|
|
76
|
+
cssl_core FUNC(str_cmp)
|
|
77
|
+
|
|
78
|
+
// Math Operations
|
|
79
|
+
cssl_core FUNC(math_clamp)
|
|
80
|
+
cssl_core FUNC(math_ipow)
|
|
81
|
+
cssl_core FUNC(math_pow)
|
|
82
|
+
cssl_core FUNC(math_mod)
|
|
83
|
+
cssl_core FUNC(math_abs)
|
|
84
|
+
cssl_core FUNC(math_min)
|
|
85
|
+
cssl_core FUNC(math_max)
|
|
86
|
+
cssl_core FUNC(math_floor)
|
|
87
|
+
cssl_core FUNC(math_ceil)
|
|
88
|
+
|
|
89
|
+
// Array Operations
|
|
90
|
+
cssl_core FUNC(array_sum)
|
|
91
|
+
cssl_core FUNC(array_isum)
|
|
92
|
+
cssl_core FUNC(array_avg)
|
|
93
|
+
cssl_core FUNC(array_min)
|
|
94
|
+
cssl_core FUNC(array_max)
|
|
95
|
+
cssl_core FUNC(range)
|
|
96
|
+
|
|
97
|
+
// Loop Helpers
|
|
98
|
+
cssl_core FUNC(loop_check_lt)
|
|
99
|
+
cssl_core FUNC(loop_check_le)
|
|
100
|
+
cssl_core FUNC(loop_check_gt)
|
|
101
|
+
cssl_core FUNC(loop_check_ge)
|
|
102
|
+
|
|
103
|
+
// Comparison Helpers
|
|
104
|
+
cssl_core FUNC(num_cmp)
|
|
105
|
+
cssl_core FUNC(eq_int)
|
|
106
|
+
cssl_core FUNC(eq_float)
|
|
107
|
+
cssl_core FUNC(eq_str)
|
|
108
|
+
)
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CSSL Lexer - High-performance tokenizer for CSSL language
|
|
3
|
+
*
|
|
4
|
+
* Part of IncludeCPP's self-hosting optimization strategy.
|
|
5
|
+
* This C++ implementation provides 10-20x speedup over Python.
|
|
6
|
+
*
|
|
7
|
+
* Copyright (c) 2024-2026 Lilias Hatterscheidt
|
|
8
|
+
* Licensed under MIT License
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
#pragma once
|
|
12
|
+
|
|
13
|
+
#include <string>
|
|
14
|
+
#include <string_view>
|
|
15
|
+
#include <vector>
|
|
16
|
+
#include <variant>
|
|
17
|
+
#include <unordered_set>
|
|
18
|
+
#include <cstdint>
|
|
19
|
+
#include <stdexcept>
|
|
20
|
+
|
|
21
|
+
namespace cssl {
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Token types matching Python cssl_parser.py TokenType enum
|
|
25
|
+
*/
|
|
26
|
+
enum class TokenType {
|
|
27
|
+
// Basic types
|
|
28
|
+
KEYWORD,
|
|
29
|
+
IDENTIFIER,
|
|
30
|
+
STRING,
|
|
31
|
+
STRING_INTERP, // <variable> in strings
|
|
32
|
+
NUMBER,
|
|
33
|
+
BOOLEAN,
|
|
34
|
+
NULL_T,
|
|
35
|
+
TYPE_LITERAL, // list, dict as type literals
|
|
36
|
+
TYPE_GENERIC, // datastruct<T>, shuffled<T>, etc.
|
|
37
|
+
|
|
38
|
+
// Injection operators
|
|
39
|
+
INJECT_LEFT, // <==
|
|
40
|
+
INJECT_RIGHT, // ==>
|
|
41
|
+
INJECT_PLUS_LEFT, // +<==
|
|
42
|
+
INJECT_PLUS_RIGHT, // ==>+
|
|
43
|
+
INJECT_MINUS_LEFT, // -<==
|
|
44
|
+
INJECT_MINUS_RIGHT, // ===>-
|
|
45
|
+
|
|
46
|
+
// Code Infusion operators
|
|
47
|
+
INFUSE_LEFT, // <<==
|
|
48
|
+
INFUSE_RIGHT, // ==>>
|
|
49
|
+
INFUSE_PLUS_LEFT, // +<<==
|
|
50
|
+
INFUSE_PLUS_RIGHT, // ==>>+
|
|
51
|
+
INFUSE_MINUS_LEFT, // -<<==
|
|
52
|
+
INFUSE_MINUS_RIGHT, // ==>>-
|
|
53
|
+
|
|
54
|
+
// Flow operators
|
|
55
|
+
FLOW_RIGHT, // ->
|
|
56
|
+
FLOW_LEFT, // <-
|
|
57
|
+
|
|
58
|
+
// Assignment and comparison
|
|
59
|
+
EQUALS, // =
|
|
60
|
+
COMPARE_EQ, // ==
|
|
61
|
+
COMPARE_NE, // !=
|
|
62
|
+
COMPARE_LT, // <
|
|
63
|
+
COMPARE_GT, // >
|
|
64
|
+
COMPARE_LE, // <=
|
|
65
|
+
COMPARE_GE, // >=
|
|
66
|
+
|
|
67
|
+
// Arithmetic
|
|
68
|
+
PLUS, // +
|
|
69
|
+
MINUS, // -
|
|
70
|
+
MULTIPLY, // *
|
|
71
|
+
DIVIDE, // /
|
|
72
|
+
MODULO, // %
|
|
73
|
+
|
|
74
|
+
// Logical
|
|
75
|
+
AND, // && or 'and'
|
|
76
|
+
OR, // || or 'or'
|
|
77
|
+
NOT, // ! or 'not'
|
|
78
|
+
AMPERSAND, // & (reference/bitwise)
|
|
79
|
+
|
|
80
|
+
// Delimiters
|
|
81
|
+
BLOCK_START, // {
|
|
82
|
+
BLOCK_END, // }
|
|
83
|
+
PAREN_START, // (
|
|
84
|
+
PAREN_END, // )
|
|
85
|
+
BRACKET_START, // [
|
|
86
|
+
BRACKET_END, // ]
|
|
87
|
+
SEMICOLON, // ;
|
|
88
|
+
COLON, // :
|
|
89
|
+
DOUBLE_COLON, // ::
|
|
90
|
+
COMMA, // ,
|
|
91
|
+
DOT, // .
|
|
92
|
+
|
|
93
|
+
// References
|
|
94
|
+
AT, // @
|
|
95
|
+
GLOBAL_REF, // r@name
|
|
96
|
+
SELF_REF, // s@name
|
|
97
|
+
SHARED_REF, // $name
|
|
98
|
+
CAPTURED_REF, // %name
|
|
99
|
+
THIS_REF, // this->
|
|
100
|
+
|
|
101
|
+
// Package/module
|
|
102
|
+
PACKAGE,
|
|
103
|
+
PACKAGE_INCLUDES,
|
|
104
|
+
AS,
|
|
105
|
+
|
|
106
|
+
// Special
|
|
107
|
+
COMMENT,
|
|
108
|
+
NEWLINE,
|
|
109
|
+
EOF_T,
|
|
110
|
+
|
|
111
|
+
// Super-functions (payload files)
|
|
112
|
+
SUPER_FUNC, // #$run(), #$exec(), etc.
|
|
113
|
+
|
|
114
|
+
// Append/extension operators
|
|
115
|
+
PLUS_PLUS, // ++ (constructor/function extension)
|
|
116
|
+
MINUS_MINUS, // --
|
|
117
|
+
|
|
118
|
+
// Multi-language support
|
|
119
|
+
LANG_INSTANCE_REF // cpp$InstanceName, py$Object
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Token value - can hold string, number, or boolean
|
|
124
|
+
*/
|
|
125
|
+
using TokenValue = std::variant<std::monostate, std::string, double, bool>;
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Token structure
|
|
129
|
+
*/
|
|
130
|
+
struct Token {
|
|
131
|
+
TokenType type;
|
|
132
|
+
TokenValue value;
|
|
133
|
+
uint32_t line;
|
|
134
|
+
uint32_t column;
|
|
135
|
+
|
|
136
|
+
// Convenience getters
|
|
137
|
+
bool has_string() const { return std::holds_alternative<std::string>(value); }
|
|
138
|
+
bool has_number() const { return std::holds_alternative<double>(value); }
|
|
139
|
+
bool has_bool() const { return std::holds_alternative<bool>(value); }
|
|
140
|
+
|
|
141
|
+
const std::string& as_string() const { return std::get<std::string>(value); }
|
|
142
|
+
double as_number() const { return std::get<double>(value); }
|
|
143
|
+
bool as_bool() const { return std::get<bool>(value); }
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Lexer error with source location
|
|
148
|
+
*/
|
|
149
|
+
class LexerError : public std::runtime_error {
|
|
150
|
+
public:
|
|
151
|
+
LexerError(const std::string& message, uint32_t line, uint32_t column,
|
|
152
|
+
const std::string& source_line = "")
|
|
153
|
+
: std::runtime_error(build_message(message, line, column, source_line)),
|
|
154
|
+
line_(line), column_(column) {}
|
|
155
|
+
|
|
156
|
+
uint32_t line() const { return line_; }
|
|
157
|
+
uint32_t column() const { return column_; }
|
|
158
|
+
|
|
159
|
+
private:
|
|
160
|
+
uint32_t line_;
|
|
161
|
+
uint32_t column_;
|
|
162
|
+
|
|
163
|
+
static std::string build_message(const std::string& msg, uint32_t line, uint32_t col,
|
|
164
|
+
const std::string& src_line) {
|
|
165
|
+
std::string result = "CSSL Lexer Error at line " + std::to_string(line) +
|
|
166
|
+
", column " + std::to_string(col) + ": " + msg;
|
|
167
|
+
if (!src_line.empty()) {
|
|
168
|
+
result += "\n " + src_line;
|
|
169
|
+
if (col > 0) {
|
|
170
|
+
result += "\n " + std::string(col - 1, ' ') + "^";
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return result;
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* High-performance CSSL Lexer
|
|
179
|
+
*
|
|
180
|
+
* Converts CSSL source code into a vector of tokens.
|
|
181
|
+
* Optimized for speed with minimal allocations.
|
|
182
|
+
*/
|
|
183
|
+
class Lexer {
|
|
184
|
+
public:
|
|
185
|
+
/**
|
|
186
|
+
* Construct lexer with source code
|
|
187
|
+
* @param source CSSL source code (must remain valid during tokenization)
|
|
188
|
+
*/
|
|
189
|
+
explicit Lexer(std::string_view source);
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Tokenize entire source and return all tokens
|
|
193
|
+
* @return Vector of tokens including EOF token at end
|
|
194
|
+
*/
|
|
195
|
+
std::vector<Token> tokenize();
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Get next token (streaming mode)
|
|
199
|
+
* @return Next token, EOF_T when done
|
|
200
|
+
*/
|
|
201
|
+
Token next_token();
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Check if more tokens available
|
|
205
|
+
*/
|
|
206
|
+
bool has_more() const { return pos_ < source_.size(); }
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Reset lexer to beginning
|
|
210
|
+
*/
|
|
211
|
+
void reset();
|
|
212
|
+
|
|
213
|
+
private:
|
|
214
|
+
std::string_view source_;
|
|
215
|
+
size_t pos_ = 0;
|
|
216
|
+
uint32_t line_ = 1;
|
|
217
|
+
uint32_t column_ = 1;
|
|
218
|
+
|
|
219
|
+
// Current character helpers
|
|
220
|
+
char current() const;
|
|
221
|
+
char peek(size_t offset = 1) const;
|
|
222
|
+
void advance(size_t count = 1);
|
|
223
|
+
bool at_end() const { return pos_ >= source_.size(); }
|
|
224
|
+
|
|
225
|
+
// Whitespace and comment handling
|
|
226
|
+
void skip_whitespace();
|
|
227
|
+
void skip_comment();
|
|
228
|
+
void skip_block_comment();
|
|
229
|
+
|
|
230
|
+
// Token readers
|
|
231
|
+
Token read_string(char quote);
|
|
232
|
+
Token read_raw_string();
|
|
233
|
+
Token read_number();
|
|
234
|
+
Token read_identifier();
|
|
235
|
+
Token read_operator();
|
|
236
|
+
|
|
237
|
+
// Special token readers
|
|
238
|
+
Token read_super_function();
|
|
239
|
+
Token read_global_ref();
|
|
240
|
+
Token read_self_ref();
|
|
241
|
+
Token read_shared_ref();
|
|
242
|
+
Token read_captured_ref();
|
|
243
|
+
|
|
244
|
+
// Operator readers
|
|
245
|
+
Token read_less_than();
|
|
246
|
+
Token read_greater_than();
|
|
247
|
+
Token read_equals();
|
|
248
|
+
Token read_not();
|
|
249
|
+
Token read_minus();
|
|
250
|
+
Token read_plus();
|
|
251
|
+
|
|
252
|
+
// Token creation helpers
|
|
253
|
+
Token make_token(TokenType type, TokenValue value = {}) const;
|
|
254
|
+
|
|
255
|
+
// Error helper
|
|
256
|
+
[[noreturn]] void error(const std::string& message) const;
|
|
257
|
+
|
|
258
|
+
// Static keyword sets (initialized once)
|
|
259
|
+
static const std::unordered_set<std::string> keywords_;
|
|
260
|
+
static const std::unordered_set<std::string> type_literals_;
|
|
261
|
+
static const std::unordered_set<std::string> type_generics_;
|
|
262
|
+
static const std::unordered_set<std::string> language_ids_;
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Utility function: Tokenize source code
|
|
267
|
+
* @param source CSSL source code
|
|
268
|
+
* @return Vector of tokens
|
|
269
|
+
*/
|
|
270
|
+
inline std::vector<Token> tokenize(const std::string& source) {
|
|
271
|
+
Lexer lexer(source);
|
|
272
|
+
return lexer.tokenize();
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Get string representation of token type
|
|
277
|
+
*/
|
|
278
|
+
const char* token_type_name(TokenType type);
|
|
279
|
+
|
|
280
|
+
} // namespace cssl
|
|
@@ -41,6 +41,7 @@ class CSSLBuiltins:
|
|
|
41
41
|
self._functions['error'] = self.builtin_error
|
|
42
42
|
self._functions['warn'] = self.builtin_warn
|
|
43
43
|
self._functions['log'] = self.builtin_log
|
|
44
|
+
self._functions['encode'] = self.builtin_encode # v4.3.2: Safe unicode encoding
|
|
44
45
|
|
|
45
46
|
# Type conversion
|
|
46
47
|
self._functions['int'] = self.builtin_int
|
|
@@ -380,6 +381,44 @@ class CSSLBuiltins:
|
|
|
380
381
|
encoded = output.encode(sys.stdout.encoding or 'utf-8', errors='replace')
|
|
381
382
|
print(encoded.decode(sys.stdout.encoding or 'utf-8', errors='replace'))
|
|
382
383
|
|
|
384
|
+
def builtin_encode(self, content: str, fallback: str = "?") -> str:
|
|
385
|
+
"""Encode unicode/emoji characters for safe console output.
|
|
386
|
+
|
|
387
|
+
v4.3.2: Safely encode emojis and special unicode characters that may not
|
|
388
|
+
be supported by the current console encoding (e.g., Windows cp1252).
|
|
389
|
+
|
|
390
|
+
Usage:
|
|
391
|
+
printl("Status: " + encode("✅"));
|
|
392
|
+
printl("Result: " + encode("😂", "[emoji]"));
|
|
393
|
+
|
|
394
|
+
// With custom fallback
|
|
395
|
+
msg = encode("🎉 Success!", "[party]");
|
|
396
|
+
|
|
397
|
+
Args:
|
|
398
|
+
content: String containing unicode/emoji characters
|
|
399
|
+
fallback: Replacement string for unencodable characters (default: "?")
|
|
400
|
+
|
|
401
|
+
Returns:
|
|
402
|
+
String safe for console output
|
|
403
|
+
"""
|
|
404
|
+
import sys
|
|
405
|
+
encoding = sys.stdout.encoding or 'utf-8'
|
|
406
|
+
|
|
407
|
+
try:
|
|
408
|
+
# Test if content can be encoded with current console encoding
|
|
409
|
+
content.encode(encoding)
|
|
410
|
+
return content
|
|
411
|
+
except UnicodeEncodeError:
|
|
412
|
+
# Replace unencodable characters with fallback
|
|
413
|
+
result = []
|
|
414
|
+
for char in content:
|
|
415
|
+
try:
|
|
416
|
+
char.encode(encoding)
|
|
417
|
+
result.append(char)
|
|
418
|
+
except UnicodeEncodeError:
|
|
419
|
+
result.append(fallback)
|
|
420
|
+
return ''.join(result)
|
|
421
|
+
|
|
383
422
|
def builtin_input(self, prompt: str = "") -> str:
|
|
384
423
|
"""Read user input from console.
|
|
385
424
|
|
|
@@ -645,19 +684,85 @@ class CSSLBuiltins:
|
|
|
645
684
|
# ============= List Functions =============
|
|
646
685
|
|
|
647
686
|
def builtin_push(self, lst: list, *items) -> list:
|
|
687
|
+
"""Push items onto a list/stack/vector.
|
|
688
|
+
|
|
689
|
+
v4.5.1: For Stack/Vector/Array types, modifies in place.
|
|
690
|
+
For regular lists, creates a copy (immutable behavior).
|
|
691
|
+
"""
|
|
692
|
+
if lst is None:
|
|
693
|
+
lst = []
|
|
694
|
+
lst.extend(items)
|
|
695
|
+
return lst
|
|
696
|
+
|
|
697
|
+
# v4.5.1: For CSSL typed containers, modify in place
|
|
698
|
+
from .cssl_types import Stack, Vector, Array, DataStruct
|
|
699
|
+
if isinstance(lst, (Stack, Vector, Array, DataStruct)):
|
|
700
|
+
for item in items:
|
|
701
|
+
lst.append(item)
|
|
702
|
+
return lst
|
|
703
|
+
|
|
704
|
+
# For regular lists, create a copy (immutable behavior)
|
|
648
705
|
lst = list(lst)
|
|
649
706
|
lst.extend(items)
|
|
650
707
|
return lst
|
|
651
708
|
|
|
652
709
|
def builtin_pop(self, lst: list, index: int = -1) -> Any:
|
|
710
|
+
"""Pop item from list/stack/vector.
|
|
711
|
+
|
|
712
|
+
v4.5.1: For Stack/Vector/Array types, modifies in place.
|
|
713
|
+
"""
|
|
714
|
+
if lst is None:
|
|
715
|
+
return None
|
|
716
|
+
|
|
717
|
+
# v4.5.1: For CSSL typed containers, modify in place
|
|
718
|
+
from .cssl_types import Stack, Vector, Array, DataStruct
|
|
719
|
+
if isinstance(lst, (Stack, Vector, Array, DataStruct)):
|
|
720
|
+
if len(lst) == 0:
|
|
721
|
+
return None
|
|
722
|
+
return lst.pop(index)
|
|
723
|
+
|
|
724
|
+
# For regular lists, create a copy
|
|
653
725
|
lst = list(lst)
|
|
654
|
-
return lst.pop(index)
|
|
726
|
+
return lst.pop(index) if lst else None
|
|
655
727
|
|
|
656
728
|
def builtin_shift(self, lst: list) -> Any:
|
|
729
|
+
"""Remove and return first element.
|
|
730
|
+
|
|
731
|
+
v4.5.1: For Stack/Vector/Array types, modifies in place.
|
|
732
|
+
"""
|
|
733
|
+
if lst is None:
|
|
734
|
+
return None
|
|
735
|
+
|
|
736
|
+
# v4.5.1: For CSSL typed containers, modify in place
|
|
737
|
+
from .cssl_types import Stack, Vector, Array, DataStruct
|
|
738
|
+
if isinstance(lst, (Stack, Vector, Array, DataStruct)):
|
|
739
|
+
if len(lst) == 0:
|
|
740
|
+
return None
|
|
741
|
+
return lst.pop(0)
|
|
742
|
+
|
|
743
|
+
# For regular lists, create a copy
|
|
657
744
|
lst = list(lst)
|
|
658
745
|
return lst.pop(0) if lst else None
|
|
659
746
|
|
|
660
747
|
def builtin_unshift(self, lst: list, *items) -> list:
|
|
748
|
+
"""Add items to the front of a list/stack/vector.
|
|
749
|
+
|
|
750
|
+
v4.5.1: For Stack/Vector/Array types, modifies in place.
|
|
751
|
+
"""
|
|
752
|
+
if lst is None:
|
|
753
|
+
lst = []
|
|
754
|
+
for item in reversed(items):
|
|
755
|
+
lst.insert(0, item)
|
|
756
|
+
return lst
|
|
757
|
+
|
|
758
|
+
# v4.5.1: For CSSL typed containers, modify in place
|
|
759
|
+
from .cssl_types import Stack, Vector, Array, DataStruct
|
|
760
|
+
if isinstance(lst, (Stack, Vector, Array, DataStruct)):
|
|
761
|
+
for item in reversed(items):
|
|
762
|
+
lst.insert(0, item)
|
|
763
|
+
return lst
|
|
764
|
+
|
|
765
|
+
# For regular lists, create a copy
|
|
661
766
|
lst = list(lst)
|
|
662
767
|
for item in reversed(items):
|
|
663
768
|
lst.insert(0, item)
|
|
@@ -2250,17 +2355,20 @@ class CSSLBuiltins:
|
|
|
2250
2355
|
|
|
2251
2356
|
All definitions go into the namespace dict.
|
|
2252
2357
|
embedded replacements are scoped to the namespace only.
|
|
2358
|
+
Variables declared with 'global' keyword remain truly global (accessible via @).
|
|
2253
2359
|
"""
|
|
2254
2360
|
# Create namespace dict
|
|
2255
2361
|
namespace = {}
|
|
2256
2362
|
|
|
2257
|
-
# Save current scope state
|
|
2258
|
-
|
|
2259
|
-
|
|
2363
|
+
# Save current scope state (copy the variables dicts)
|
|
2364
|
+
old_scope_vars = dict(self.runtime.scope.variables)
|
|
2365
|
+
old_global_vars = dict(self.runtime.global_scope.variables)
|
|
2366
|
+
old_promoted_globals = dict(self.runtime._promoted_globals)
|
|
2260
2367
|
|
|
2261
2368
|
# Track what gets added during payload execution
|
|
2262
|
-
scope_before = set(self.runtime.scope.keys())
|
|
2263
|
-
global_before = set(self.runtime.global_scope.keys())
|
|
2369
|
+
scope_before = set(self.runtime.scope.variables.keys())
|
|
2370
|
+
global_before = set(self.runtime.global_scope.variables.keys())
|
|
2371
|
+
promoted_before = set(self.runtime._promoted_globals.keys())
|
|
2264
2372
|
|
|
2265
2373
|
# Set a flag to tell runtime we're in namespace mode
|
|
2266
2374
|
self.runtime._payload_namespace_mode = libname
|
|
@@ -2269,46 +2377,53 @@ class CSSLBuiltins:
|
|
|
2269
2377
|
# Execute the payload
|
|
2270
2378
|
self.runtime._execute_node(ast)
|
|
2271
2379
|
|
|
2272
|
-
#
|
|
2273
|
-
|
|
2274
|
-
if key not in scope_before:
|
|
2275
|
-
namespace[key] = self.runtime.scope[key]
|
|
2380
|
+
# Find which variables were explicitly promoted to global (via 'global' keyword)
|
|
2381
|
+
new_promoted = set(self.runtime._promoted_globals.keys()) - promoted_before
|
|
2276
2382
|
|
|
2277
|
-
# Collect new definitions from
|
|
2278
|
-
for key in self.runtime.
|
|
2279
|
-
if key not in
|
|
2280
|
-
namespace[key] = self.runtime.
|
|
2383
|
+
# Collect new definitions from scope (but not promoted globals)
|
|
2384
|
+
for key in self.runtime.scope.variables:
|
|
2385
|
+
if key not in scope_before and key not in new_promoted:
|
|
2386
|
+
namespace[key] = self.runtime.scope.get(key)
|
|
2387
|
+
|
|
2388
|
+
# Collect new definitions from global_scope (but not namespace itself, not promoted globals)
|
|
2389
|
+
for key in self.runtime.global_scope.variables:
|
|
2390
|
+
if key not in global_before and key != libname and key not in new_promoted:
|
|
2391
|
+
namespace[key] = self.runtime.global_scope.get(key)
|
|
2281
2392
|
|
|
2282
2393
|
# Handle embedded replacements: move replaced targets into namespace
|
|
2283
2394
|
if hasattr(self.runtime, '_namespace_replacements'):
|
|
2284
2395
|
for target_name, new_impl in self.runtime._namespace_replacements.items():
|
|
2285
2396
|
# Get the original from before execution
|
|
2286
|
-
original =
|
|
2397
|
+
original = old_scope_vars.get(target_name) or old_global_vars.get(target_name)
|
|
2287
2398
|
if original is not None:
|
|
2288
2399
|
# Restore original globally
|
|
2289
|
-
if target_name in
|
|
2290
|
-
self.runtime.scope
|
|
2291
|
-
if target_name in
|
|
2292
|
-
self.runtime.global_scope
|
|
2400
|
+
if target_name in old_scope_vars:
|
|
2401
|
+
self.runtime.scope.set(target_name, original)
|
|
2402
|
+
if target_name in old_global_vars:
|
|
2403
|
+
self.runtime.global_scope.set(target_name, original)
|
|
2293
2404
|
# Put the replacement in namespace
|
|
2294
2405
|
namespace[target_name] = new_impl
|
|
2295
2406
|
del self.runtime._namespace_replacements
|
|
2296
2407
|
|
|
2297
|
-
# Remove new definitions from
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2408
|
+
# Remove new definitions from scope (they're in namespace now)
|
|
2409
|
+
# BUT keep promoted globals - they stay global!
|
|
2410
|
+
for key in list(self.runtime.scope.variables.keys()):
|
|
2411
|
+
if key not in scope_before and key not in new_promoted:
|
|
2412
|
+
del self.runtime.scope.variables[key]
|
|
2413
|
+
|
|
2414
|
+
for key in list(self.runtime.global_scope.variables.keys()):
|
|
2415
|
+
if key not in global_before and key != libname and key not in new_promoted:
|
|
2416
|
+
del self.runtime.global_scope.variables[key]
|
|
2301
2417
|
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
del self.runtime.global_scope[key]
|
|
2418
|
+
# Promoted globals stay in _promoted_globals and global_scope (not moved to namespace)
|
|
2419
|
+
# They are accessible via @name from anywhere
|
|
2305
2420
|
|
|
2306
2421
|
finally:
|
|
2307
2422
|
# Clear namespace mode flag
|
|
2308
2423
|
self.runtime._payload_namespace_mode = None
|
|
2309
2424
|
|
|
2310
2425
|
# Register namespace in global scope
|
|
2311
|
-
self.runtime.global_scope
|
|
2426
|
+
self.runtime.global_scope.set(libname, namespace)
|
|
2312
2427
|
|
|
2313
2428
|
def builtin_get(self, source: Any, key: str = None) -> Any:
|
|
2314
2429
|
"""
|