cluaupp 0.1.2 → 0.1.4

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.
Files changed (64) hide show
  1. package/CHANGELOG.md +20 -1
  2. package/README.md +5 -8
  3. package/docs/README.md +13 -10
  4. package/docs/architecture.md +18 -11
  5. package/docs/cli.md +2 -2
  6. package/docs/config.md +1 -1
  7. package/docs/cpp-advanced.md +10 -6
  8. package/docs/cpp-organization.md +3 -1
  9. package/docs/cpp-safety.md +11 -7
  10. package/docs/cpp-types.md +1 -1
  11. package/docs/examples/_category_.json +5 -0
  12. package/docs/examples/combat.md +239 -0
  13. package/docs/examples/data-boot.md +98 -0
  14. package/docs/examples/hud.md +96 -0
  15. package/docs/examples/index.md +43 -0
  16. package/docs/examples/leaderstats.md +140 -0
  17. package/docs/examples/shop.md +122 -0
  18. package/docs/examples/sword.md +108 -0
  19. package/docs/getting-started.md +12 -6
  20. package/docs/intellisense.md +31 -0
  21. package/docs/intro.md +2 -2
  22. package/docs/libraries/_category_.json +5 -0
  23. package/docs/libraries/dataservice.md +104 -0
  24. package/docs/libraries/index.md +22 -0
  25. package/docs/libraries/janitor.md +65 -0
  26. package/docs/libraries/more.md +79 -0
  27. package/docs/libraries/net.md +35 -0
  28. package/docs/libraries/promise.md +27 -0
  29. package/docs/oop/_category_.json +5 -0
  30. package/docs/oop/file-tags.md +49 -0
  31. package/docs/oop/index.md +22 -0
  32. package/docs/oop/modules.md +86 -0
  33. package/docs/oop/services.md +83 -0
  34. package/docs/print-cout.md +91 -0
  35. package/docs/syntax.md +59 -5
  36. package/editors/vscode/extension.js +146 -0
  37. package/editors/vscode/package.json +25 -0
  38. package/include/cluaupp/libs/janitor.hpp +7 -3
  39. package/include/cluaupp/roblox.hpp +19 -0
  40. package/package.json +66 -65
  41. package/runtime/Janitor/init.luau +4 -34
  42. package/src/architecture.js +108 -48
  43. package/src/cli.js +85 -10
  44. package/src/client/init.client.cpp +5 -0
  45. package/src/compile.js +20 -4
  46. package/src/editor-install.js +218 -0
  47. package/src/emit.js +320 -8
  48. package/src/intellisense.js +1368 -0
  49. package/src/layout.js +129 -0
  50. package/src/lex.js +17 -9
  51. package/src/libs.js +95 -16
  52. package/src/lsp.js +227 -0
  53. package/src/parse.js +187 -6
  54. package/src/preprocess.js +71 -3
  55. package/src/server/leaderstats.server.cpp +28 -0
  56. package/src/shared/config.cpp +5 -0
  57. package/src/shared/config.h +3 -0
  58. package/src/understand.js +64 -6
  59. package/templates/game/.clangd +11 -0
  60. package/templates/game/.vscode/c_cpp_properties.json +6 -2
  61. package/templates/game/.vscode/extensions.json +6 -0
  62. package/templates/game/.vscode/settings.json +16 -2
  63. package/templates/game/compile_flags.txt +2 -0
  64. package/docs/libraries.md +0 -80
package/docs/syntax.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Cluaupp is not a full C++ compiler. It is a **subset** aimed at Roblox scripts, in the same spirit as roblox-ts (restricted TypeScript → Luau).
4
4
 
5
- Generated Luau follows the current language: [`--!strict`](https://luau.org/getting-started), `local`, and `const`.
5
+ Generated Luau follows the current language: [`--!strict`](https://luau.org/getting-started), `local`, `const`, and `const function`. Injected `require` / `GetService` lines are `const`.
6
6
 
7
7
  ## Files
8
8
 
@@ -25,11 +25,11 @@ int doubleCoins(int coins) {
25
25
  ```
26
26
 
27
27
  ```luau
28
- local function CreateLeaderstats(player: Player)
28
+ const function CreateLeaderstats(player: Player)
29
29
  return
30
30
  end
31
31
 
32
- local function doubleCoins(coins: number): number
32
+ const function doubleCoins(coins: number): number
33
33
  return coins
34
34
  end
35
35
  ```
@@ -73,6 +73,22 @@ while (true) {
73
73
  for (auto* player : players->GetPlayers()) {
74
74
  CreateLeaderstats(player);
75
75
  }
76
+
77
+ switch (action) {
78
+ case "buy":
79
+ case "purchase":
80
+ Grant(player);
81
+ break;
82
+ case "sell":
83
+ if (amount <= 0) {
84
+ break;
85
+ }
86
+ Take(player);
87
+ break;
88
+ default:
89
+ warn("unknown");
90
+ break;
91
+ }
76
92
  ```
77
93
 
78
94
  ```luau
@@ -89,9 +105,22 @@ end
89
105
  for _, player in players:GetPlayers() do
90
106
  CreateLeaderstats(player)
91
107
  end
108
+
109
+ repeat
110
+ if action == "buy" or action == "purchase" then
111
+ Grant(player)
112
+ elseif action == "sell" then
113
+ if amount <= 0 then
114
+ break
115
+ end
116
+ Take(player)
117
+ else
118
+ warn("unknown")
119
+ end
120
+ until true
92
121
  ```
93
122
 
94
- The only `for` accepted today is **range-for**: `for (auto* x : list)`. C-style `for (int i = 0; i < n; i++)` is not supported yet.
123
+ `switch` evaluates the discriminant **once**, then becomes `if` / `elseif` / `else` inside `repeat … until true` so `break` still exits the switch (even from inside an `if`). Stacked `case` labels share a body (`case "buy": case "purchase":`). There is no C-style fall-through into the next case’s statements. C-style `for (int i = 0; i < n; i++)` is not supported yet.
95
124
 
96
125
  ## Expressions
97
126
 
@@ -143,8 +172,33 @@ local players: Players = game:GetService("Players")
143
172
 
144
173
  The first argument of `new Class(parent)` becomes `.Parent`. With no argument: `Instance.new("Class")` only.
145
174
 
175
+ ## print / cout
176
+
177
+ `print`, `warn`, and `error` work as in Luau. `cout << … << endl` is the C++ spelling — each `<<` is another argument, `endl` ends the line. `cout::warn` / `cout::error` / `cout::ping` pick the Roblox function.
178
+
179
+ ```cpp
180
+ cout << "EnsureStat: " << name << " not found" << endl;
181
+ cout::print << "EnsureStat: " << name << " not found" << endl;
182
+ cerr << "failed";
183
+ cout::print("ok");
184
+ cout::warn("careful");
185
+ cout::error("fail");
186
+ cout::ping("here");
187
+ ```
188
+
189
+ ```luau
190
+ print("EnsureStat: ", name, " not found")
191
+ warn("failed")
192
+ print("ok")
193
+ warn("careful")
194
+ error("fail")
195
+ print("here")
196
+ ```
197
+
198
+ Full table and IntelliSense notes: [print and cout](print-cout.md).
199
+
146
200
  ## Not supported yet
147
201
 
148
- Custom C++ classes, generic templates besides `GetService<T>`, pointer arithmetic, `switch`, `std::`, overloading, macros (except skipping `#` lines).
202
+ Custom C++ classes, generic templates besides `GetService<T>`, pointer arithmetic, `std::`, overloading, macros (except skipping `#` lines).
149
203
 
150
204
  If you need one of those patterns, open an issue with the C++ and the expected Luau.
@@ -0,0 +1,146 @@
1
+ "use strict";
2
+
3
+ const fs = require("fs");
4
+ const path = require("path");
5
+ const vscode = require("vscode");
6
+
7
+ function loadEngine(context) {
8
+ const folders = vscode.workspace.workspaceFolders || [];
9
+ const workspaceFolder = folders[0] ? folders[0].uri.fsPath : null;
10
+ const rootFile = path.join(context.extensionPath, "cluaupp.root");
11
+ const roots = [];
12
+ if (fs.existsSync(rootFile)) {
13
+ roots.push(fs.readFileSync(rootFile, "utf8").trim());
14
+ }
15
+ if (workspaceFolder) {
16
+ roots.push(path.join(workspaceFolder, "..", "Cluaupp"));
17
+ roots.push(path.join(workspaceFolder, "node_modules", "cluaupp"));
18
+ }
19
+ roots.push(path.join(context.extensionPath, "..", ".."));
20
+ for (const root of roots) {
21
+ const engine = path.join(root, "src", "intellisense.js");
22
+ if (fs.existsSync(engine)) {
23
+ return { engine: require(engine), root, workspaceFolder };
24
+ }
25
+ }
26
+ throw new Error("Cluaupp IntelliSense engine not found. Run `cluaupp intellisense` in the game folder.");
27
+ }
28
+
29
+ function kindOf(kind) {
30
+ const map = {
31
+ method: vscode.CompletionItemKind.Method,
32
+ function: vscode.CompletionItemKind.Function,
33
+ constructor: vscode.CompletionItemKind.Constructor,
34
+ property: vscode.CompletionItemKind.Property,
35
+ variable: vscode.CompletionItemKind.Variable,
36
+ class: vscode.CompletionItemKind.Class,
37
+ enum: vscode.CompletionItemKind.Enum,
38
+ keyword: vscode.CompletionItemKind.Keyword,
39
+ event: vscode.CompletionItemKind.Event,
40
+ file: vscode.CompletionItemKind.File,
41
+ };
42
+ return map[kind] || vscode.CompletionItemKind.Text;
43
+ }
44
+
45
+ function activate(context) {
46
+ let loaded;
47
+ try {
48
+ loaded = loadEngine(context);
49
+ } catch (err) {
50
+ vscode.window.showWarningMessage(String(err.message || err));
51
+ return;
52
+ }
53
+
54
+ const selector = { language: "cpp", scheme: "file" };
55
+ const diagnostics = vscode.languages.createDiagnosticCollection("cluaupp");
56
+ context.subscriptions.push(diagnostics);
57
+
58
+ const optionsFor = (document) => ({
59
+ projectRoot: loaded.workspaceFolder || path.dirname(document.uri.fsPath),
60
+ file: document.uri.fsPath,
61
+ filePath: document.uri.fsPath,
62
+ includeDirs: [
63
+ path.dirname(document.uri.fsPath),
64
+ path.join(loaded.workspaceFolder || "", "src"),
65
+ path.join(loaded.workspaceFolder || "", "include"),
66
+ ],
67
+ });
68
+
69
+ const refreshDiagnostics = (document) => {
70
+ if (!document || document.languageId !== "cpp") {
71
+ return;
72
+ }
73
+ const items = loaded.engine.diagnosticsFor(document.getText(), document.uri.fsPath, optionsFor(document));
74
+ diagnostics.set(
75
+ document.uri,
76
+ items.map((item) => {
77
+ const line = Math.max(0, (item.line || 1) - 1);
78
+ const col = Math.max(0, (item.col || 1) - 1);
79
+ const range = new vscode.Range(line, col, line, col + 1);
80
+ return new vscode.Diagnostic(range, item.message, vscode.DiagnosticSeverity.Error);
81
+ }),
82
+ );
83
+ };
84
+
85
+ context.subscriptions.push(
86
+ vscode.languages.registerCompletionItemProvider(
87
+ selector,
88
+ {
89
+ provideCompletionItems(document, position) {
90
+ const offset = document.offsetAt(position);
91
+ const items = loaded.engine.completeAt(document.getText(), offset, optionsFor(document));
92
+ return items.map((item) => {
93
+ const completion = new vscode.CompletionItem(item.name, kindOf(item.kind));
94
+ completion.detail = item.detail || item.type || "";
95
+ completion.sortText = `${item.kind === "keyword" ? "2" : "0"}_${item.name}`;
96
+ completion.insertText = item.name;
97
+ return completion;
98
+ });
99
+ },
100
+ },
101
+ ".",
102
+ ":",
103
+ ">",
104
+ "<",
105
+ '"',
106
+ "/",
107
+ ),
108
+ vscode.languages.registerHoverProvider(selector, {
109
+ provideHover(document, position) {
110
+ const hover = loaded.engine.hoverAt(document.getText(), document.offsetAt(position), optionsFor(document));
111
+ if (!hover) {
112
+ return null;
113
+ }
114
+ return new vscode.Hover(new vscode.MarkdownString(`**${hover.name}**\n\n\`${hover.detail || hover.type || ""}\``));
115
+ },
116
+ }),
117
+ vscode.languages.registerDefinitionProvider(selector, {
118
+ provideDefinition(document, position) {
119
+ const def = loaded.engine.definitionAt(document.getText(), document.offsetAt(position), optionsFor(document));
120
+ if (!def || !def.file) {
121
+ return null;
122
+ }
123
+ return new vscode.Location(vscode.Uri.file(def.file), new vscode.Position(Math.max(0, (def.line || 1) - 1), 0));
124
+ },
125
+ }),
126
+ vscode.workspace.onDidChangeTextDocument((event) => refreshDiagnostics(event.document)),
127
+ vscode.workspace.onDidOpenTextDocument(refreshDiagnostics),
128
+ vscode.commands.registerCommand("cluaupp.restartIntelliSense", () => {
129
+ try {
130
+ delete require.cache[require.resolve(path.join(loaded.root, "src", "intellisense.js"))];
131
+ loaded = loadEngine(context);
132
+ vscode.window.showInformationMessage("Cluaupp IntelliSense reloaded.");
133
+ } catch (err) {
134
+ vscode.window.showErrorMessage(String(err.message || err));
135
+ }
136
+ }),
137
+ );
138
+
139
+ for (const document of vscode.workspace.textDocuments) {
140
+ refreshDiagnostics(document);
141
+ }
142
+ }
143
+
144
+ function deactivate() {}
145
+
146
+ module.exports = { activate, deactivate };
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "cluaupp-intellisense",
3
+ "displayName": "Cluaupp IntelliSense",
4
+ "description": "Completions, hover, and go-to-definition for Cluaupp C++ (Roblox APIs, DataService paths, project structs).",
5
+ "version": "0.1.4",
6
+ "publisher": "kartzdev",
7
+ "engines": {
8
+ "vscode": "^1.74.0"
9
+ },
10
+ "categories": [
11
+ "Programming Languages"
12
+ ],
13
+ "activationEvents": [
14
+ "onLanguage:cpp"
15
+ ],
16
+ "main": "./extension.js",
17
+ "contributes": {
18
+ "commands": [
19
+ {
20
+ "command": "cluaupp.restartIntelliSense",
21
+ "title": "Cluaupp: Restart IntelliSense"
22
+ }
23
+ ]
24
+ }
25
+ }
@@ -10,6 +10,8 @@ public:
10
10
  template <typename T>
11
11
  T Add(T object);
12
12
  template <typename T>
13
+ T Add(T object, bool callDirectly);
14
+ template <typename T>
13
15
  T Add(T object, string methodName);
14
16
  template <typename T>
15
17
  T Add(T object, string methodName, string index);
@@ -17,14 +19,15 @@ public:
17
19
  T AddObject(T constructor);
18
20
  template <typename P>
19
21
  P AddPromise(P promise);
22
+ template <typename P>
23
+ P AddPromise(P promise, string index);
20
24
  Janitor* Remove(string index);
21
25
  Janitor* RemoveNoClean(string index);
22
26
  Janitor* RemoveList(string index);
27
+ Janitor* RemoveListNoClean(string index);
23
28
  template <typename T>
24
29
  T Get(string index);
25
- template <typename T>
26
- T GetAll();
27
- bool Has(string index);
30
+ void GetAll();
28
31
  void Cleanup();
29
32
  void Destroy();
30
33
  RBXScriptConnection LinkToInstance(Instance* object);
@@ -32,4 +35,5 @@ public:
32
35
  Janitor* LinkToInstances(Instance* object);
33
36
  static bool Is(Instance* value);
34
37
  static bool Is(string value);
38
+ static bool instanceof(Instance* value);
35
39
  };
@@ -21,6 +21,25 @@ extern LuaSourceContainer* script;
21
21
  void print(string message);
22
22
  void warn(string message);
23
23
  void error(string message);
24
+
25
+ struct cout {
26
+ static void print(string message);
27
+ static void warn(string message);
28
+ static void error(string message);
29
+ static void ping(string message);
30
+ static void endl();
31
+ cout& operator<<(string value);
32
+ cout& operator<<(int value);
33
+ cout& operator<<(double value);
34
+ cout& operator<<(bool value);
35
+ } cout;
36
+
37
+ struct cerr {
38
+ cerr& operator<<(string value);
39
+ cerr& operator<<(int value);
40
+ } cerr;
41
+
42
+ const int endl = 0;
24
43
  double tick();
25
44
  double time();
26
45
  void wait(double seconds = 0);
package/package.json CHANGED
@@ -1,65 +1,66 @@
1
- {
2
- "name": "cluaupp",
3
- "version": "0.1.2",
4
- "description": "Cluaupp — the definitive merge of C++ and modern Luau. Source-to-source transpiler with first-class Roblox APIs.",
5
- "author": "KartzDev",
6
- "license": "MIT",
7
- "bin": {
8
- "cluaupp": "bin/cluaupp.js",
9
- "cluau": "bin/cluaupp.js"
10
- },
11
- "main": "src/compile.js",
12
- "exports": {
13
- ".": "./src/compile.js",
14
- "./package.json": "./package.json"
15
- },
16
- "files": [
17
- "bin",
18
- "src",
19
- "include",
20
- "templates",
21
- "runtime",
22
- "README.md",
23
- "LICENSE",
24
- "CHANGELOG.md",
25
- "docs"
26
- ],
27
- "scripts": {
28
- "cluaupp": "node bin/cluaupp.js",
29
- "cluau": "node bin/cluaupp.js",
30
- "build": "node bin/cluaupp.js build",
31
- "watch": "node bin/cluaupp.js watch",
32
- "test": "node test/leaderstats.test.js && node test/understand.test.js && node test/datatypes.test.js && node test/headers.test.js && node test/libs.test.js && node test/runtime-libs.test.js && node test/intellisense.test.js && node test/dataservice.test.js && node test/prune.test.js && node test/hold.test.js",
33
- "generate-api": "node scripts/generate-api.js",
34
- "check-highlight": "node scripts/check-highlight.js",
35
- "vendor-libs": "node scripts/vendor-libs.js",
36
- "docs": "moonwave dev",
37
- "docs:build": "moonwave build",
38
- "site": "node scripts/generate-api.js && node scripts/check-highlight.js",
39
- "dev": "node scripts/dev.js",
40
- "stop": "node scripts/stop.js",
41
- "prepublishOnly": "npm test"
42
- },
43
- "engines": {
44
- "node": ">=18"
45
- },
46
- "keywords": [
47
- "luau",
48
- "roblox",
49
- "cpp",
50
- "c++",
51
- "transpiler",
52
- "compiler",
53
- "rojo",
54
- "cluaupp",
55
- "cluau"
56
- ],
57
- "repository": {
58
- "type": "git",
59
- "url": "git+https://github.com/KartzRbx/Cluaupp.git"
60
- },
61
- "bugs": {
62
- "url": "https://github.com/KartzRbx/Cluaupp/issues"
63
- },
64
- "homepage": "https://github.com/KartzRbx/Cluaupp#readme"
65
- }
1
+ {
2
+ "name": "cluaupp",
3
+ "version": "0.1.4",
4
+ "description": "Cluaupp — the definitive merge of C++ and modern Luau. Source-to-source transpiler with first-class Roblox APIs.",
5
+ "author": "KartzDev",
6
+ "license": "MIT",
7
+ "bin": {
8
+ "cluaupp": "bin/cluaupp.js",
9
+ "cluau": "bin/cluaupp.js"
10
+ },
11
+ "main": "src/compile.js",
12
+ "exports": {
13
+ ".": "./src/compile.js",
14
+ "./package.json": "./package.json"
15
+ },
16
+ "files": [
17
+ "bin",
18
+ "src",
19
+ "include",
20
+ "templates",
21
+ "editors",
22
+ "runtime",
23
+ "README.md",
24
+ "LICENSE",
25
+ "CHANGELOG.md",
26
+ "docs"
27
+ ],
28
+ "scripts": {
29
+ "cluaupp": "node bin/cluaupp.js",
30
+ "cluau": "node bin/cluaupp.js",
31
+ "build": "node bin/cluaupp.js build",
32
+ "watch": "node bin/cluaupp.js watch",
33
+ "test": "node test/leaderstats.test.js && node test/understand.test.js && node test/datatypes.test.js && node test/headers.test.js && node test/libs.test.js && node test/runtime-libs.test.js && node test/intellisense.test.js && node test/intellisense-complete.test.js && node test/dataservice.test.js && node test/datacontroller-signal.test.js && node test/cout.test.js && node test/prune.test.js && node test/hold.test.js && node test/vendor-stable.test.js && node test/switch.test.js && node test/qualified.test.js && node test/module-require.test.js",
34
+ "generate-api": "node scripts/generate-api.js",
35
+ "check-highlight": "node scripts/check-highlight.js",
36
+ "vendor-libs": "node scripts/vendor-libs.js",
37
+ "docs": "moonwave dev",
38
+ "docs:build": "moonwave build",
39
+ "site": "node scripts/generate-api.js && node scripts/check-highlight.js",
40
+ "dev": "node scripts/dev.js",
41
+ "stop": "node scripts/stop.js",
42
+ "prepublishOnly": "npm test"
43
+ },
44
+ "engines": {
45
+ "node": ">=18"
46
+ },
47
+ "keywords": [
48
+ "luau",
49
+ "roblox",
50
+ "cpp",
51
+ "c++",
52
+ "transpiler",
53
+ "compiler",
54
+ "rojo",
55
+ "cluaupp",
56
+ "cluau"
57
+ ],
58
+ "repository": {
59
+ "type": "git",
60
+ "url": "git+https://github.com/KartzRbx/Cluaupp.git"
61
+ },
62
+ "bugs": {
63
+ "url": "https://github.com/KartzRbx/Cluaupp/issues"
64
+ },
65
+ "homepage": "https://github.com/KartzRbx/Cluaupp#readme"
66
+ }
@@ -1,45 +1,15 @@
1
1
  --!strict
2
2
  -- Cluaupp Janitor — typed border. Engine: howmanysmall/Janitor (_impl).
3
- -- Requires the sibling CluauppLibs.Promise module, never a nested stub.
3
+ -- Public type and return value are the implementation. Promise is required
4
+ -- inside _impl as CluauppLibs.Promise (`script.Parent.Parent.Promise`).
4
5
 
5
6
  --[=[
6
7
  @class Janitor
7
8
  Cleans up connections, instances, promises, and threads.
8
9
  ]=]
9
10
 
10
- local PromiseMod = require(script.Parent.Promise)
11
- type Promise<T...> = PromiseMod.Promise<T...>
12
-
13
11
  local Impl = require(script._impl)
14
12
 
15
- export type Janitor = {
16
- CurrentlyCleaning: boolean,
17
- SuppressInstanceReDestroy: boolean,
18
- UnsafeThreadCleanup: boolean,
19
- Add: <T>(self: Janitor, object: T, methodName: (boolean | string)?, index: string?) -> T,
20
- AddObject: <T, A...>(
21
- self: Janitor,
22
- constructor: { new: (A...) -> T },
23
- methodName: (boolean | string)?,
24
- index: string?,
25
- A...
26
- ) -> T,
27
- AddPromise: <T...>(self: Janitor, promiseObject: Promise<T...>, index: string?) -> Promise<T...>,
28
- Remove: (self: Janitor, index: string) -> Janitor,
29
- RemoveNoClean: (self: Janitor, index: string) -> Janitor,
30
- RemoveList: (self: Janitor, ...string) -> Janitor,
31
- Get: <T>(self: Janitor, index: string) -> T?,
32
- GetAll: (self: Janitor) -> { [string]: unknown },
33
- Has: (self: Janitor, index: string) -> boolean,
34
- Cleanup: (self: Janitor) -> (),
35
- Destroy: (self: Janitor) -> (),
36
- LinkToInstance: (self: Janitor, object: Instance, allowMultiple: boolean?) -> RBXScriptConnection,
37
- LinkToInstances: (self: Janitor, ...Instance) -> Janitor,
38
- }
39
-
40
- type JanitorStatic = {
41
- new: () -> Janitor,
42
- Is: (value: unknown) -> boolean,
43
- }
13
+ export type Janitor = Impl.Janitor
44
14
 
45
- return Impl :: JanitorStatic
15
+ return Impl