gemite 0.1.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: eedb79d9169824c4dd1acd1b0d458c406641a99d6ee73ad54b9fd8a611145ba1
4
+ data.tar.gz: 6819f25750a7c35ea9f7cd801291eb00f2a756f03c17d43457476e1408f2f191
5
+ SHA512:
6
+ metadata.gz: f1b830f0c22159cf6ba313d15c1089914f504dfacdaa802130816e981017799e848b1a0699c053d6a244e8e5c72db418894ad76df3332b91873212d9a96cfea5
7
+ data.tar.gz: 48fa83f5f96976adfb69ee4461351ae6425cc199c5ecb6e08a09de549a254790845058e113f023fe4e98105317c45a581dc559d536542cbe48217890cf1dd84f
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Araki-Tomoya
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,519 @@
1
+ # Gemite
2
+
3
+ > **A lightweight HTML-first programming language for building small web applications.**
4
+
5
+ Gemite is a lightweight programming language inspired by PHP. It lets you create dynamic web applications by embedding Gemite code directly into HTML.
6
+
7
+ Its philosophy is simple:
8
+
9
+ * HTML first
10
+ * No framework
11
+ * No configuration
12
+ * Small and fast
13
+ * Easy deployment
14
+
15
+ ---
16
+
17
+ # Features
18
+
19
+ * HTML-first syntax
20
+ * File-based routing
21
+ * Built-in development server
22
+ * SQLite support
23
+ * Cross-platform (Windows, Linux, macOS)
24
+ * Minimal dependencies
25
+ * Easy to learn
26
+ * Ruby-powered runtime
27
+
28
+ ---
29
+
30
+ # Installation
31
+
32
+ Install from RubyGems.
33
+
34
+ ```sh
35
+ gem install gemite
36
+ ```
37
+
38
+ Check the installed version.
39
+
40
+ ```sh
41
+ gemite version
42
+ ```
43
+
44
+ ---
45
+
46
+ # Quick Start
47
+
48
+ Create a new project.
49
+
50
+ ```sh
51
+ mkdir myapp
52
+ cd myapp
53
+ ```
54
+
55
+ Create `index.gmt`.
56
+
57
+ ```html
58
+ <?gemite
59
+ name = "Gemite"
60
+ ?>
61
+
62
+ <!DOCTYPE html>
63
+
64
+ <html>
65
+ <head>
66
+ <title>Gemite</title>
67
+ </head>
68
+
69
+ <body>
70
+ <h1>Hello, {name}!</h1>
71
+ </body>
72
+ </html>
73
+ ```
74
+
75
+ Run the development server.
76
+
77
+ ```sh
78
+ gemite
79
+ ```
80
+
81
+ Open your browser.
82
+
83
+ ```
84
+ http://localhost:8000
85
+ ```
86
+
87
+ ---
88
+
89
+ # Project Structure
90
+
91
+ ```
92
+ myapp/
93
+
94
+ ├── index.gmt
95
+ ├── about.gmt
96
+ ├── users/
97
+ │ └── list.gmt
98
+
99
+ ├── public/
100
+ │ ├── css/
101
+ │ ├── js/
102
+ │ └── images/
103
+
104
+ └── database.db
105
+ ```
106
+
107
+ URL mapping
108
+
109
+ ```
110
+ index.gmt
111
+
112
+ /
113
+
114
+ about.gmt
115
+
116
+ /about
117
+
118
+ users/list.gmt
119
+
120
+ /users/list
121
+ ```
122
+
123
+ ---
124
+
125
+ # Language Guide
126
+
127
+ ## Comments
128
+
129
+ ```gemite
130
+ // Single line comment
131
+ ```
132
+
133
+ ---
134
+
135
+ ## Variables
136
+
137
+ ```gemite
138
+ name = "Gemite"
139
+ count = 10
140
+ ```
141
+
142
+ ---
143
+
144
+ ## Numbers
145
+
146
+ ```gemite
147
+ a = 10
148
+ b = 3.14
149
+ ```
150
+
151
+ ---
152
+
153
+ ## Strings
154
+
155
+ ```gemite
156
+ name = "Gemite"
157
+ ```
158
+
159
+ ---
160
+
161
+ ## Boolean
162
+
163
+ ```gemite
164
+ true
165
+ false
166
+ ```
167
+
168
+ ---
169
+
170
+ ## Arrays
171
+
172
+ ```gemite
173
+ items = [1,2,3]
174
+ ```
175
+
176
+ ---
177
+
178
+ ## Maps
179
+
180
+ ```gemite
181
+ user = Map()
182
+ ```
183
+
184
+ ---
185
+
186
+ ## Operators
187
+
188
+ Arithmetic
189
+
190
+ ```
191
+ +
192
+ -
193
+ *
194
+ /
195
+ %
196
+ ```
197
+
198
+ Comparison
199
+
200
+ ```
201
+ ==
202
+ !=
203
+ <
204
+ <=
205
+ >
206
+ >=
207
+ ```
208
+
209
+ Logical
210
+
211
+ ```
212
+ &&
213
+ ||
214
+ !
215
+ ```
216
+
217
+ ---
218
+
219
+ ## if
220
+
221
+ ```gemite
222
+ if score >= 60
223
+ print("Pass")
224
+ end
225
+ ```
226
+
227
+ ---
228
+
229
+ ## unless
230
+
231
+ ```gemite
232
+ unless logged_in
233
+ print("Login required")
234
+ end
235
+ ```
236
+
237
+ ---
238
+
239
+ ## while
240
+
241
+ ```gemite
242
+ while i < 10
243
+ i += 1
244
+ end
245
+ ```
246
+
247
+ ---
248
+
249
+ ## for
250
+
251
+ ```gemite
252
+ for i = 0; i < 10; i += 1
253
+ print(i)
254
+ end
255
+ ```
256
+
257
+ ---
258
+
259
+ ## foreach
260
+
261
+ ```gemite
262
+ foreach item in items
263
+ print(item)
264
+ end
265
+ ```
266
+
267
+ ---
268
+
269
+ ## break
270
+
271
+ ```gemite
272
+ break
273
+ ```
274
+
275
+ ---
276
+
277
+ ## continue
278
+
279
+ ```gemite
280
+ continue
281
+ ```
282
+
283
+ ---
284
+
285
+ ## return
286
+
287
+ ```gemite
288
+ return value
289
+ ```
290
+
291
+ ---
292
+
293
+ ## Functions
294
+
295
+ ```gemite
296
+ func hello(name)
297
+ print(name)
298
+ end
299
+ ```
300
+
301
+ ---
302
+
303
+ ## HTML Output
304
+
305
+ ```html
306
+ <h1>{title}</h1>
307
+ ```
308
+
309
+ Expressions inside `{}` are evaluated and inserted into HTML.
310
+
311
+ ---
312
+
313
+ # Built-in Functions
314
+
315
+ String
316
+
317
+ ```
318
+ len()
319
+
320
+ substr()
321
+
322
+ split()
323
+
324
+ join()
325
+
326
+ replace()
327
+
328
+ upper()
329
+
330
+ lower()
331
+
332
+ trim()
333
+ ```
334
+
335
+ Math
336
+
337
+ ```
338
+ abs()
339
+
340
+ rand()
341
+
342
+ min()
343
+
344
+ max()
345
+ ```
346
+
347
+ Time
348
+
349
+ ```
350
+ time()
351
+
352
+ sleep()
353
+ ```
354
+
355
+ Files
356
+
357
+ ```
358
+ exists()
359
+
360
+ read()
361
+
362
+ write()
363
+
364
+ append()
365
+
366
+ delete()
367
+
368
+ mkdir()
369
+
370
+ copy()
371
+
372
+ move()
373
+ ```
374
+
375
+ JSON
376
+
377
+ ```
378
+ json_encode()
379
+
380
+ json_decode()
381
+ ```
382
+
383
+ SQLite
384
+
385
+ ```
386
+ db.open()
387
+
388
+ db.query()
389
+
390
+ db.exec()
391
+
392
+ db.close()
393
+ ```
394
+
395
+ ---
396
+
397
+ # CLI Commands
398
+
399
+ Start the development server.
400
+
401
+ ```sh
402
+ gemite
403
+ ```
404
+
405
+ Specify a port.
406
+
407
+ ```sh
408
+ gemite s 3000
409
+ ```
410
+
411
+ Show the version.
412
+
413
+ ```sh
414
+ gemite version
415
+ ```
416
+
417
+ Show help.
418
+
419
+ ```sh
420
+ gemite help
421
+ ```
422
+
423
+ ---
424
+
425
+ # Examples
426
+
427
+ ## Hello World
428
+
429
+ ```html
430
+ <?gemite
431
+ name = "World"
432
+ ?>
433
+
434
+ <h1>Hello, {name}!</h1>
435
+ ```
436
+
437
+ ---
438
+
439
+ ## Counter
440
+
441
+ ```gemite
442
+ count = count + 1
443
+ ```
444
+
445
+ ---
446
+
447
+ ## SQLite
448
+
449
+ ```gemite
450
+ db = db.open("database.db")
451
+ rows = db.query("SELECT * FROM users")
452
+ ```
453
+
454
+ ---
455
+
456
+ # Build
457
+
458
+ Clone the repository.
459
+
460
+ ```sh
461
+ git clone https://github.com/<YOUR_GITHUB>/gemite.git
462
+ cd gemite
463
+ ```
464
+
465
+ Build the gem.
466
+
467
+ ```sh
468
+ gem build gemite.gemspec
469
+ ```
470
+
471
+ This creates:
472
+
473
+ ```
474
+ gemite-x.y.z.gem
475
+ ```
476
+
477
+ ---
478
+
479
+ # Install from Source
480
+
481
+ ```sh
482
+ gem install ./gemite-x.y.z.gem
483
+ ```
484
+
485
+ Verify the installation.
486
+
487
+ ```sh
488
+ gemite version
489
+ ```
490
+
491
+ ---
492
+
493
+ # Development
494
+
495
+ Install dependencies.
496
+
497
+ ```sh
498
+ bundle install
499
+ ```
500
+
501
+ Run Gemite from the source tree.
502
+
503
+ ```sh
504
+ bundle exec gemite
505
+ ```
506
+
507
+ or
508
+
509
+ ```sh
510
+ ruby exe/gemite
511
+ ```
512
+
513
+ ---
514
+
515
+ # License
516
+
517
+ Gemite is released under the MIT License.
518
+
519
+ See the `LICENSE` file for details.
@@ -0,0 +1,13 @@
1
+ # サンプル: コメント投稿アプリ
2
+
3
+ Gemite言語仕様書のPHP移植例(section 28)をそのまま `.gmt` にしたものです。
4
+
5
+ ## 実行方法
6
+
7
+ ```sh
8
+ cd examples/comments
9
+ gemite
10
+ ```
11
+
12
+ `http://localhost:8000` を開いてコメントを投稿してみてください。
13
+ `comments.db` (SQLite) にそのまま保存され、再起動しても消えません。
@@ -0,0 +1,65 @@
1
+ <?gemite
2
+
3
+ db = sqlite("comments.db")
4
+
5
+ db.exec("
6
+ CREATE TABLE IF NOT EXISTS comments(
7
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
8
+ body TEXT
9
+ )
10
+ ")
11
+
12
+ @if post
13
+
14
+ db.insert(
15
+ "comments",
16
+ {
17
+ body: post.body
18
+ }
19
+ )
20
+
21
+ redirect("/")
22
+
23
+ @endif
24
+
25
+ comments =
26
+ db.select(
27
+ "comments"
28
+ )
29
+
30
+ ?>
31
+
32
+ <!DOCTYPE html>
33
+ <html>
34
+ <head>
35
+ <meta charset="utf-8">
36
+ <title>コメント - Gemite Example</title>
37
+ <link rel="stylesheet" href="/css/style.css">
38
+ </head>
39
+ <body>
40
+
41
+ <h1>コメント</h1>
42
+
43
+ <form method="post">
44
+
45
+ <input
46
+ type="text"
47
+ name="body"
48
+ placeholder="コメントを入力">
49
+
50
+ <input
51
+ type="submit"
52
+ value="投稿">
53
+
54
+ </form>
55
+
56
+ <hr>
57
+
58
+ @for comment in comments
59
+
60
+ <p>{comment.body}</p>
61
+
62
+ @end
63
+
64
+ </body>
65
+ </html>
@@ -0,0 +1,44 @@
1
+ body {
2
+ font-family: -apple-system, "Hiragino Kaku Gothic ProN", sans-serif;
3
+ max-width: 640px;
4
+ margin: 3rem auto;
5
+ padding: 0 1rem;
6
+ color: #222;
7
+ }
8
+
9
+ h1 {
10
+ border-bottom: 3px solid #333;
11
+ padding-bottom: 0.5rem;
12
+ }
13
+
14
+ form {
15
+ display: flex;
16
+ gap: 0.5rem;
17
+ margin: 1.5rem 0;
18
+ }
19
+
20
+ input[type="text"] {
21
+ flex: 1;
22
+ padding: 0.5rem;
23
+ border: 1px solid #ccc;
24
+ border-radius: 4px;
25
+ }
26
+
27
+ input[type="submit"] {
28
+ padding: 0.5rem 1rem;
29
+ border: none;
30
+ border-radius: 4px;
31
+ background: #333;
32
+ color: #fff;
33
+ cursor: pointer;
34
+ }
35
+
36
+ input[type="submit"]:hover {
37
+ background: #555;
38
+ }
39
+
40
+ hr {
41
+ border: none;
42
+ border-top: 1px solid #eee;
43
+ margin: 1.5rem 0;
44
+ }
data/exe/gemite ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require_relative "../lib/gemite"
5
+
6
+ Gemite::CLI.run(ARGV)
data/lib/gemite/ast.rb ADDED
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gemite
4
+ module AST
5
+ # ---------- 式 (Expression) ----------
6
+ IntLiteral = Struct.new(:value)
7
+ FloatLiteral = Struct.new(:value)
8
+ # parts: [:str, "text"] または [:expr, ast] の配列("#{}"補間対応)
9
+ StringLiteral = Struct.new(:parts)
10
+ BoolLiteral = Struct.new(:value)
11
+ NilLiteral = Struct.new(:value)
12
+ ArrayLiteral = Struct.new(:elements)
13
+ # pairs: [key_symbol, value_ast] の配列
14
+ HashLiteral = Struct.new(:pairs)
15
+ Identifier = Struct.new(:name)
16
+ BinaryOp = Struct.new(:op, :left, :right)
17
+ UnaryOp = Struct.new(:op, :operand)
18
+ LogicalOp = Struct.new(:op, :left, :right)
19
+ MemberAccess = Struct.new(:receiver, :name)
20
+ IndexAccess = Struct.new(:receiver, :index)
21
+ CallExpr = Struct.new(:callee_name, :args)
22
+ MethodCallExpr = Struct.new(:receiver, :method_name, :args)
23
+
24
+ # ---------- 文 (Statement) ----------
25
+ Assignment = Struct.new(:name, :value)
26
+ FunctionDef = Struct.new(:name, :params, :body)
27
+ ReturnStmt = Struct.new(:value)
28
+ ExprStmt = Struct.new(:expr)
29
+ # branches: [[cond_ast, [stmt,...]], ...]
30
+ IfStmt = Struct.new(:branches, :else_body)
31
+ ForStmt = Struct.new(:var_name, :iterable, :body)
32
+ BeginCatchStmt = Struct.new(:begin_body, :err_name, :catch_body)
33
+
34
+ # ---------- テンプレートノード (HTML生テキスト側) ----------
35
+ TplText = Struct.new(:text)
36
+ TplExpr = Struct.new(:expr)
37
+ TplCode = Struct.new(:statements)
38
+ # branches: [[cond_ast, [tpl_node,...]], ...]
39
+ TplIf = Struct.new(:branches, :else_body)
40
+ TplFor = Struct.new(:var_name, :iterable, :body)
41
+ end
42
+ end