cajyu 0.0.0-stage → 1.0.0

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.
package/README.md CHANGED
@@ -1,3 +1,197 @@
1
- # Temporary Holding Version
1
+ # Cajyu
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ **A clean, practical programming language that transpiles to JavaScript.**
4
+
5
+ Cajyu is designed for people who want a simpler syntax without leaving the JavaScript ecosystem. Write expressive code, get real JavaScript output, and use a growing set of official libraries.
6
+
7
+ [![npm](https://img.shields.io/badge/npm-cajyu-blue)](https://www.npmjs.com/package/cajyu)
8
+ [![License](https://img.shields.io/badge/license-MIT-green)](LICENSE)
9
+
10
+ ---
11
+
12
+ ## Features
13
+
14
+ - **Familiar yet cleaner syntax** — variables, functions, classes, control flow, and loops that feel natural
15
+ - **Transpiles to modern JavaScript** — runs anywhere Node.js runs
16
+ - **Real HTTP server** — built-in `Server` class with POST handlers, sleep/wake, and static files
17
+ - **Official libraries** — `serial`, `fs`, `math`, `http` (and more coming)
18
+ - **Optional typing** — runtime type checks with `var x:Number = 10`
19
+ - **Async support** — `sync fn` and `wait`
20
+ - **One-liners & stacking** — concise style when you want it
21
+ - **CLI** — `cajyu init`, `cajyu inst`, `cajyu run`
22
+
23
+ ---
24
+
25
+ ## Quick Start
26
+
27
+ ```bash
28
+ # Install the CLI (once published)
29
+ npm install -g cajyu
30
+
31
+ # Or run directly from this repo
32
+ node bin/cajyu.js --help
33
+ ```
34
+
35
+ Create a new project:
36
+
37
+ ```bash
38
+ cajyu init
39
+ ```
40
+
41
+ Run a file:
42
+
43
+ ```bash
44
+ cajyu run examples/fatorial.cjy
45
+ ```
46
+
47
+ ---
48
+
49
+ ## Syntax Overview
50
+
51
+ ### Variables
52
+ ```cajyu
53
+ var name = "Cajyu"
54
+ var age:Number = 17
55
+ var items = [1, 2, 3]
56
+ ```
57
+
58
+ ### Functions
59
+ ```cajyu
60
+ fn add a, b {
61
+ return a + b
62
+ }
63
+
64
+ fn double x {
65
+ return x * 2
66
+ }
67
+ ```
68
+
69
+ ### Control Flow
70
+ ```cajyu
71
+ if x > 10 {
72
+ print("big")
73
+ } elif x > 5 {
74
+ print("medium")
75
+ } else {
76
+ print("small")
77
+ }
78
+ ```
79
+
80
+ ### Loops
81
+ ```cajyu
82
+ for i in range(10) {
83
+ print(i)
84
+ }
85
+
86
+ while x < 100 {
87
+ x = x * 2
88
+ }
89
+ ```
90
+
91
+ ### Classes
92
+ ```cajyu
93
+ class Person {
94
+ Main name, age {
95
+ Self.name = name
96
+ Self.age = age
97
+ }
98
+ greet {
99
+ return "Hello, I'm " + Self.name
100
+ }
101
+ }
102
+
103
+ var p = new Person("Ana", 17)
104
+ print(p.greet())
105
+ ```
106
+
107
+ ### Async
108
+ ```cajyu
109
+ sync fn fetchData {
110
+ wait someAsyncCall()
111
+ return result
112
+ }
113
+ ```
114
+
115
+ ### HTTP Server
116
+ ```cajyu
117
+ import Server from CajyuLibs.http
118
+ import print from CajyuLibs.serial
119
+
120
+ var server = new Server(3000)
121
+
122
+ server.post(fn b {
123
+ if !b.a and !b.b {
124
+ return { code: 400 }
125
+ }
126
+ return {
127
+ code: 200,
128
+ result: b.a + b.b
129
+ }
130
+ })
131
+ ```
132
+
133
+ ---
134
+
135
+ ## Libraries
136
+
137
+ Official libraries live in the [CajyuLibs](https://github.com/abs-js/CajyuLibs) repository.
138
+
139
+ Install a library:
140
+
141
+ ```bash
142
+ cajyu inst serial
143
+ cajyu inst http
144
+ ```
145
+
146
+ Import in your code:
147
+
148
+ ```cajyu
149
+ import print from CajyuLibs.serial
150
+ import Server from CajyuLibs.http
151
+ ```
152
+
153
+ ---
154
+
155
+ ## CLI Commands
156
+
157
+ | Command | Description |
158
+ |---------|-------------|
159
+ | `cajyu init` | Create a new project (`package.json` + structure) |
160
+ | `cajyu inst <name>` | Install a library from CajyuLibs |
161
+ | `cajyu run <file.cjy>` | Compile and run a Cajyu file |
162
+
163
+ ---
164
+
165
+ ## Project Structure
166
+
167
+ ```
168
+ Cajyu/
169
+ ├── bin/cajyu.js # CLI entry point
170
+ ├── src/compiler.js # Transpiler
171
+ ├── examples/ # Working examples
172
+ │ ├── fatorial.cjy
173
+ │ ├── classe.cjy
174
+ │ └── servidor-post.cjy
175
+ └── package.json
176
+ ```
177
+
178
+ ---
179
+
180
+ ## Contributing
181
+
182
+ Cajyu is early but intentional. Pull requests are welcome — especially for:
183
+
184
+ - A proper parser (currently regex-based)
185
+ - More language features
186
+ - New official libraries
187
+ - Better error messages
188
+
189
+ ---
190
+
191
+ ## License
192
+
193
+ MIT
194
+
195
+ ---
196
+
197
+ **Built for people who like clean code and real results.**
@@ -0,0 +1,16 @@
1
+ import print from CajyuLibs.serial
2
+
3
+ class Pessoa {
4
+ Main nome, idade {
5
+ Self.nome = nome
6
+ Self.idade = idade
7
+ }
8
+ // private nome
9
+ // private idade
10
+ apresentar {
11
+ return "Oi, eu sou " + Self.nome + " e tenho " + Self.idade + " anos"
12
+ }
13
+ }
14
+
15
+ var p = new Pessoa("Ana", 17)
16
+ print(p.apresentar())
@@ -0,0 +1,13 @@
1
+ import print from CajyuLibs.serial
2
+
3
+ fn fac a {
4
+ if a <= 1 {
5
+ return 1
6
+ } else {
7
+ return a * fac(a - 1)
8
+ }
9
+ }
10
+
11
+ for i in range(10) {
12
+ print(fac(i));
13
+ }
@@ -0,0 +1,18 @@
1
+ import Server from CajyuLibs.http
2
+ import print from CajyuLibs.serial
3
+
4
+ var server = new Server(3000)
5
+ print("Servidor Cajyu pronto na porta 3000")
6
+
7
+ server.post(fn b {
8
+ if !b.a and !b.b {
9
+ return { code: 400 }
10
+ }
11
+ return {
12
+ code: 200,
13
+ result: b.a + b.b
14
+ }
15
+ })
16
+
17
+ print("POST / com JSON {a, b} para somar")
18
+ print("server.sleep() e server.wake() disponíveis")
package/package.json CHANGED
@@ -1,6 +1,17 @@
1
1
  {
2
2
  "name": "cajyu",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "1.0.0",
4
+ "description": "Cajyu programming language - a custom language that compiles to JavaScript",
5
+ "main": "src/compiler.js",
6
+ "bin": {
7
+ "cajyu": "./bin/cajyu.js"
8
+ },
9
+ "scripts": {
10
+ "start": "node bin/cajyu.js"
11
+ },
12
+ "keywords": ["cajyu", "compiler", "language", "javascript"],
13
+ "author": "Cajyu Team",
14
+ "license": "MIT",
15
+ "dependencies": {},
16
+ "type": "module"
17
+ }
@@ -0,0 +1,149 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import { pathToFileURL } from 'url';
4
+
5
+ export async function compileAndRun(filePath) {
6
+ if (!fs.existsSync(filePath)) {
7
+ console.error(`Arquivo não encontrado: ${filePath}`);
8
+ process.exit(1);
9
+ }
10
+ const source = fs.readFileSync(filePath, 'utf-8');
11
+ const jsCode = transpile(source, path.dirname(filePath));
12
+ const tempFile = path.join('/tmp', `cajyu_${Date.now()}.mjs`);
13
+ fs.writeFileSync(tempFile, jsCode);
14
+ try {
15
+ await import(pathToFileURL(tempFile).href);
16
+ console.log('--- Execução Cajyu ---');
17
+ } catch (err) {
18
+ console.error('Erro na execução:', err.message);
19
+ console.error(err.stack);
20
+ } finally {
21
+ try { fs.unlinkSync(tempFile); } catch {}
22
+ }
23
+ }
24
+
25
+ function transpile(source, baseDir) {
26
+ const lines = source.split('\n');
27
+ const imports = [];
28
+ const codeLines = [];
29
+ for (const line of lines) {
30
+ const m = line.match(/^\s*import\s+(\*|\w+)\s+from\s+['"]?([^\s'"]+)['"]?\s*;?\s*$/);
31
+ if (m) imports.push({ what: m[1], from: m[2] });
32
+ else codeLines.push(line);
33
+ }
34
+ let code = codeLines.join('\n');
35
+
36
+ let importCode = '';
37
+ for (const imp of imports) {
38
+ const libPath = resolveLib(imp.from, baseDir);
39
+ if (libPath && fs.existsSync(libPath)) {
40
+ const url = pathToFileURL(libPath).href;
41
+ if (imp.what === '*') {
42
+ importCode += `const _lib = await import('${url}'); Object.assign(globalThis, _lib.CayjuLib || _lib);\n`;
43
+ } else {
44
+ importCode += `const { CayjuLib: _lib${imp.what} } = await import('${url}'); const ${imp.what} = _lib${imp.what}.${imp.what} || _lib${imp.what};\n`;
45
+ }
46
+ }
47
+ }
48
+
49
+ code = preprocessKeywords(code);
50
+ code = transpileFunctions(code);
51
+ code = transpileAnonymousFunctions(code);
52
+ code = transpileControlFlow(code);
53
+ code = transpileOneLiners(code);
54
+
55
+ const builtins = `
56
+ function _range(a, b, c) {
57
+ const r = [];
58
+ if (b == null) for (let i = 1; i <= a; i++) r.push(i);
59
+ else if (c == null) for (let i = a; i <= b; i++) r.push(i);
60
+ else for (let i = a; i <= b; i += c) r.push(i);
61
+ return r;
62
+ }
63
+ function _typeCheck(val, type) {
64
+ if (!type) return val;
65
+ const t = String(type).toLowerCase();
66
+ if (t === 'string' && typeof val !== 'string') throw new Error('esperado String');
67
+ if ((t === 'number' || t === 'int' || t === 'float') && typeof val !== 'number') throw new Error('esperado Number');
68
+ if (t === 'boolean' && typeof val !== 'boolean') throw new Error('esperado Boolean');
69
+ if (t === 'array' && !Array.isArray(val)) throw new Error('esperado Array');
70
+ return val;
71
+ }
72
+ `;
73
+
74
+ const final = `
75
+ ${importCode}
76
+ ${builtins}
77
+ (async () => {
78
+ ${code}
79
+ })().catch(console.error);
80
+ `;
81
+
82
+ fs.writeFileSync('/tmp/cajyu_debug.mjs', final);
83
+ return final;
84
+ }
85
+
86
+ function resolveLib(from, baseDir) {
87
+ if (from.startsWith('CajyuLibs')) {
88
+ const name = from.split('.')[1] || 'serial';
89
+ const cands = [
90
+ path.resolve(baseDir, 'CajyuLibs', name, 'main.js'),
91
+ path.resolve(baseDir, '..', 'CajyuLibs', name, 'main.js'),
92
+ path.resolve(process.cwd(), 'CajyuLibs', name, 'main.js'),
93
+ ];
94
+ return cands.find(p => fs.existsSync(p));
95
+ }
96
+ return path.resolve(baseDir, from);
97
+ }
98
+
99
+ function cleanParams(s) {
100
+ return (s || '').trim().split(',').map(p => p.trim().split(':')[0].trim()).filter(Boolean).join(', ');
101
+ }
102
+
103
+ function preprocessKeywords(code) {
104
+ return code
105
+ .replace(/\band\b/g, '&&')
106
+ .replace(/\bor\b/g, '||')
107
+ .replace(/\bnot\b/g, '!')
108
+ .replace(/sync\s+fn\s+(\w+)/g, 'async function $1')
109
+ .replace(/\bwait\s+/g, 'await ')
110
+ .replace(/\belif\b/g, 'else if')
111
+ .replace(/\bSelf\./g, 'this.')
112
+ .replace(/\brange\(/g, '_range(')
113
+ .replace(/\/\/\s*private\s+(\w+)/g, '/* private $1 */')
114
+ .replace(/var\s+(\w+):(\w+)\s*=\s*(.+)/g, 'let $1 = _typeCheck($3, "$2")')
115
+ .replace(/var\s+(\w+)\s*=/g, 'let $1 =');
116
+ }
117
+
118
+ function transpileFunctions(code) {
119
+ return code
120
+ .replace(/^fn\s+(\w+)\s+([^{]*)\{/gm, (_, n, p) => `function ${n}(${cleanParams(p)}) {`)
121
+ .replace(/^fn\s+(\w+)\s*\{/gm, 'function $1() {')
122
+ .replace(/Main\s+([^{]*)\{/g, (_, p) => `constructor(${cleanParams(p)}) {`)
123
+ .replace(/^\s*(\w+)\s*\{/gm, (m, name) => {
124
+ const keywords = ['if','else','while','for','return','class','fn','function','constructor'];
125
+ if (keywords.includes(name)) return m;
126
+ return ` ${name}() {`;
127
+ });
128
+ }
129
+
130
+ function transpileAnonymousFunctions(code) {
131
+ return code.replace(/(?<!^|\n)fn\s+([^{]*)\{/g, (_, params) => {
132
+ const p = cleanParams(params);
133
+ return `function(${p}) {`;
134
+ });
135
+ }
136
+
137
+ function transpileControlFlow(code) {
138
+ return code
139
+ .replace(/if\s+([^{]+?)\s*\{/g, 'if ($1) {')
140
+ .replace(/else\s+if\s+([^{]+?)\s*\{/g, 'else if ($1) {')
141
+ .replace(/while\s+([^{]+?)\s*\{/g, 'while ($1) {')
142
+ .replace(/for\s+(\w+)\s+in\s+([^ {\n]+)(\s*\{)/g, 'for (let $1 of $2) $3');
143
+ }
144
+
145
+ function transpileOneLiners(code) {
146
+ return code
147
+ .replace(/return\s+(\{[^}]*\}|.+?)\s+if\s+([^;]+);/g, 'if ($2) return $1;')
148
+ .replace(/if\s+([^:{;\n]+)\s+return\s+([^;\n{]+)/g, 'if ($1) return $2;');
149
+ }