├── .gitignore ├── CMakeLists.txt ├── EXAMPLES.md ├── LICENSE.md ├── README.md ├── changelog.md ├── cmake └── modules │ └── glms_deps.cmake ├── docs ├── integration.md └── signatures.md ├── glms.png ├── include └── glms │ ├── allocator.h │ ├── ast.h │ ├── ast_type.h │ ├── buffer.h │ ├── builtin.h │ ├── constants.h │ ├── dl.h │ ├── emit │ ├── emit.h │ └── glsl │ │ └── emit_glsl.h │ ├── env.h │ ├── eval.h │ ├── fptr.h │ ├── glms.h │ ├── io.h │ ├── iterator.h │ ├── lexer.h │ ├── list.h │ ├── macros.h │ ├── math.h │ ├── modules │ ├── array.h │ ├── fetch.h │ ├── file.h │ ├── image.h │ ├── iterator.h │ ├── json.h │ ├── mat3.h │ ├── mat4.h │ ├── string.h │ ├── vec2.h │ ├── vec3.h │ └── vec4.h │ ├── parser.h │ ├── stack.h │ ├── string_builder.h │ ├── string_view.h │ ├── token.h │ ├── type.h │ └── version.h ├── profile.sh ├── release.sh ├── sample ├── and_and.gs ├── array.gs ├── array_includes.gs ├── assets │ └── somefile.json ├── basic.gs ├── bool.gs ├── cantor.gs ├── child.gs ├── cos_sin.gs ├── dot.gs ├── emit.glsl ├── enum.gs ├── extension.gs ├── extension2.gs ├── fetch_json.gs ├── file.gs ├── filter.gs ├── for.gs ├── func.gs ├── func2.gs ├── func_glsl_style.gs ├── greeting.gs ├── hash_comment.gs ├── image.gs ├── image2.gs ├── image3.gs ├── image4.gs ├── image_circle.gs ├── image_load.gs ├── include │ └── utils.glsl ├── int.gs ├── json.gs ├── lerp.gs ├── loop.gs ├── map.gs ├── material.gs ├── math.gs ├── matrix.gs ├── mul.gs ├── object.gs ├── or.gs ├── pbr.gs ├── pow.gs ├── print.gs ├── quat.gs ├── reassign.gs ├── self.gs ├── smoothstep.gs ├── sort.gs ├── string.gs ├── string_includes.gs ├── struct.gs ├── structfunc.gs ├── template_string.gs ├── test.gs ├── uint64.gs ├── use_include.gs └── vec.gs ├── src ├── allocator.c ├── ast.c ├── ast_to_string.c ├── builtin.c ├── dl.c ├── emit │ ├── emit.c │ └── glsl │ │ └── emit_glsl.c ├── env.c ├── eval.c ├── glms.c ├── io.c ├── lexer.c ├── main.c ├── math.c ├── modules │ ├── array.c │ ├── fetch.c │ ├── file.c │ ├── image.c │ ├── iterator.c │ ├── json.c │ ├── mat3.c │ ├── mat4.c │ ├── string.c │ ├── vec2.c │ ├── vec3.c │ └── vec4.c ├── parser.c ├── stack.c ├── string_builder.c ├── string_view.c ├── token.c └── type.c └── test ├── CMakeLists.txt ├── samples ├── add_add.gs ├── array.gs ├── arrow_func.gs ├── clamp.gs ├── cos_sin.gs ├── for.gs ├── func.gs ├── if.gs ├── minmax.gs ├── mix.gs ├── object.gs ├── plus_equals.gs ├── self.gs ├── struct.gs ├── sub_sub.gs ├── template_string.gs ├── var.gs ├── varfunc.gs ├── vec.gs └── while.gs └── src └── main.c /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.toptal.com/developers/gitignore/api/vim,emacs,node,yarn,npm,gcc,C++,g++,c++,CPP,cpp,cmake 2 | # Edit at https://www.toptal.com/developers/gitignore?templates=vim,emacs,node,yarn,npm,gcc,C++,g++,c++,CPP,cpp,cmake 3 | 4 | ### C++ ### 5 | # Prerequisites 6 | *.d 7 | 8 | # Compiled Object files 9 | *.slo 10 | *.lo 11 | *.o 12 | *.obj 13 | 14 | # Precompiled Headers 15 | *.gch 16 | *.pch 17 | 18 | # Compiled Dynamic libraries 19 | *.so 20 | *.dylib 21 | *.dll 22 | 23 | # Fortran module files 24 | *.mod 25 | *.smod 26 | 27 | # Compiled Static libraries 28 | *.lai 29 | *.la 30 | *.a 31 | *.lib 32 | 33 | # Executables 34 | *.exe 35 | *.out 36 | *.app 37 | 38 | ### CMake ### 39 | CMakeLists.txt.user 40 | CMakeCache.txt 41 | CMakeFiles 42 | CMakeScripts 43 | Testing 44 | Makefile 45 | cmake_install.cmake 46 | install_manifest.txt 47 | compile_commands.json 48 | CTestTestfile.cmake 49 | _deps 50 | 51 | ### CMake Patch ### 52 | # External projects 53 | *-prefix/ 54 | 55 | #!! ERROR: cpp is undefined. Use list command to see defined gitignore types !!# 56 | 57 | ### Emacs ### 58 | # -*- mode: gitignore; -*- 59 | *~ 60 | \#*\# 61 | /.emacs.desktop 62 | /.emacs.desktop.lock 63 | *.elc 64 | auto-save-list 65 | tramp 66 | .\#* 67 | 68 | # Org-mode 69 | .org-id-locations 70 | *_archive 71 | 72 | # flymake-mode 73 | *_flymake.* 74 | 75 | # eshell files 76 | /eshell/history 77 | /eshell/lastdir 78 | 79 | # elpa packages 80 | /elpa/ 81 | 82 | # reftex files 83 | *.rel 84 | 85 | # AUCTeX auto folder 86 | /auto/ 87 | 88 | # cask packages 89 | .cask/ 90 | dist/ 91 | 92 | # Flycheck 93 | flycheck_*.el 94 | 95 | # server auth directory 96 | /server/ 97 | 98 | # projectiles files 99 | .projectile 100 | 101 | # directory configuration 102 | .dir-locals.el 103 | 104 | # network security 105 | /network-security.data 106 | 107 | 108 | #!! ERROR: g++ is undefined. Use list command to see defined gitignore types !!# 109 | 110 | #!! ERROR: gcc is undefined. Use list command to see defined gitignore types !!# 111 | 112 | ### Node ### 113 | # Logs 114 | logs 115 | *.log 116 | npm-debug.log* 117 | yarn-debug.log* 118 | yarn-error.log* 119 | lerna-debug.log* 120 | .pnpm-debug.log* 121 | 122 | # Diagnostic reports (https://nodejs.org/api/report.html) 123 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 124 | 125 | # Runtime data 126 | pids 127 | *.pid 128 | *.seed 129 | *.pid.lock 130 | 131 | # Directory for instrumented libs generated by jscoverage/JSCover 132 | lib-cov 133 | 134 | # Coverage directory used by tools like istanbul 135 | coverage 136 | *.lcov 137 | 138 | # nyc test coverage 139 | .nyc_output 140 | 141 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 142 | .grunt 143 | 144 | # Bower dependency directory (https://bower.io/) 145 | bower_components 146 | 147 | # node-waf configuration 148 | .lock-wscript 149 | 150 | # Compiled binary addons (https://nodejs.org/api/addons.html) 151 | build/Release 152 | 153 | # Dependency directories 154 | node_modules/ 155 | jspm_packages/ 156 | 157 | # Snowpack dependency directory (https://snowpack.dev/) 158 | web_modules/ 159 | 160 | # TypeScript cache 161 | *.tsbuildinfo 162 | 163 | # Optional npm cache directory 164 | .npm 165 | 166 | # Optional eslint cache 167 | .eslintcache 168 | 169 | # Optional stylelint cache 170 | .stylelintcache 171 | 172 | # Microbundle cache 173 | .rpt2_cache/ 174 | .rts2_cache_cjs/ 175 | .rts2_cache_es/ 176 | .rts2_cache_umd/ 177 | 178 | # Optional REPL history 179 | .node_repl_history 180 | 181 | # Output of 'npm pack' 182 | *.tgz 183 | 184 | # Yarn Integrity file 185 | .yarn-integrity 186 | 187 | # dotenv environment variable files 188 | .env 189 | .env.development.local 190 | .env.test.local 191 | .env.production.local 192 | .env.local 193 | 194 | # parcel-bundler cache (https://parceljs.org/) 195 | .cache 196 | .parcel-cache 197 | 198 | # Next.js build output 199 | .next 200 | out 201 | 202 | # Nuxt.js build / generate output 203 | .nuxt 204 | dist 205 | 206 | # Gatsby files 207 | .cache/ 208 | # Comment in the public line in if your project uses Gatsby and not Next.js 209 | # https://nextjs.org/blog/next-9-1#public-directory-support 210 | # public 211 | 212 | # vuepress build output 213 | .vuepress/dist 214 | 215 | # vuepress v2.x temp and cache directory 216 | .temp 217 | 218 | # Docusaurus cache and generated files 219 | .docusaurus 220 | 221 | # Serverless directories 222 | .serverless/ 223 | 224 | # FuseBox cache 225 | .fusebox/ 226 | 227 | # DynamoDB Local files 228 | .dynamodb/ 229 | 230 | # TernJS port file 231 | .tern-port 232 | 233 | # Stores VSCode versions used for testing VSCode extensions 234 | .vscode-test 235 | 236 | # yarn v2 237 | .yarn/cache 238 | .yarn/unplugged 239 | .yarn/build-state.yml 240 | .yarn/install-state.gz 241 | .pnp.* 242 | 243 | ### Node Patch ### 244 | # Serverless Webpack directories 245 | .webpack/ 246 | 247 | # Optional stylelint cache 248 | 249 | # SvelteKit build / generate output 250 | .svelte-kit 251 | 252 | #!! ERROR: npm is undefined. Use list command to see defined gitignore types !!# 253 | 254 | ### Vim ### 255 | # Swap 256 | [._]*.s[a-v][a-z] 257 | !*.svg # comment out if you don't need vector files 258 | [._]*.sw[a-p] 259 | [._]s[a-rt-v][a-z] 260 | [._]ss[a-gi-z] 261 | [._]sw[a-p] 262 | 263 | # Session 264 | Session.vim 265 | Sessionx.vim 266 | 267 | # Temporary 268 | .netrwhist 269 | # Auto-generated tag files 270 | tags 271 | # Persistent undo 272 | [._]*.un~ 273 | 274 | ### yarn ### 275 | # https://yarnpkg.com/getting-started/qa#which-files-should-be-gitignored 276 | 277 | .yarn/* 278 | !.yarn/releases 279 | !.yarn/patches 280 | !.yarn/plugins 281 | !.yarn/sdks 282 | !.yarn/versions 283 | 284 | # if you are NOT using Zero-installs, then: 285 | # comment the following lines 286 | !.yarn/cache 287 | 288 | # and uncomment the following lines 289 | # .pnp.* 290 | 291 | # End of https://www.toptal.com/developers/gitignore/api/vim,emacs,node,yarn,npm,gcc,C++,g++,c++,CPP,cpp,cmake 292 | build/ 293 | /assets/ 294 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.20) 2 | 3 | set (CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules") 4 | 5 | include(glms_deps) 6 | 7 | project(glms) 8 | 9 | set(CMAKE_EXPORT_COMPILE_COMMANDS ON CACHE INTERNAL ${CMAKE_CURRENT_SOURCE_DIR}/) 10 | set(COMMANDS_FILE ${CMAKE_CURRENT_SOURCE_DIR}/compile_commands.json) 11 | 12 | if (EXISTS ${COMMANDS_FILE}) 13 | file(COPY ${COMMANDS_FILE} DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/) 14 | endif() 15 | 16 | 17 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) 18 | 19 | file( 20 | GLOB 21 | sourcefiles 22 | ${CMAKE_CURRENT_SOURCE_DIR}/src/*.c 23 | ${CMAKE_CURRENT_SOURCE_DIR}/src/emit/*.c 24 | ${CMAKE_CURRENT_SOURCE_DIR}/src/emit/glsl/*.c 25 | ${CMAKE_CURRENT_SOURCE_DIR}/src/modules/*.c 26 | ) 27 | 28 | #file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/assets DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) 29 | 30 | add_executable(glms_e ${sourcefiles}) 31 | list(FILTER sourcefiles EXCLUDE REGEX "main.c") 32 | add_library(glms SHARED ${sourcefiles}) 33 | add_library(glms_static STATIC ${sourcefiles}) 34 | 35 | 36 | # set (GLMS_DEBUG_FLAGS -g -Wall) 37 | set (GLMS_DEBUG_FLAGS ) 38 | 39 | target_compile_options(glms_e PRIVATE ${GLMS_DEBUG_FLAGS}) 40 | target_compile_options(glms PRIVATE ${GLMS_DEBUG_FLAGS}) 41 | target_compile_options(glms_static PRIVATE ${GLMS_DEBUG_FLAGS}) 42 | 43 | 44 | target_include_directories( 45 | glms 46 | PUBLIC 47 | $ 48 | $ 49 | $ 50 | ${CMAKE_CURRENT_BINARY_DIR}/include 51 | ${CMAKE_CURRENT_SOURCE_DIR}/include) 52 | 53 | 54 | 55 | target_include_directories( 56 | glms_static 57 | PUBLIC 58 | $ 59 | $ 60 | $ 61 | ${CMAKE_CURRENT_BINARY_DIR}/include 62 | ${CMAKE_CURRENT_SOURCE_DIR}/include) 63 | 64 | 65 | glms_deps(glms) 66 | glms_deps(glms_e) 67 | glms_deps(glms_static) 68 | 69 | 70 | add_subdirectory(test) 71 | -------------------------------------------------------------------------------- /EXAMPLES.md: -------------------------------------------------------------------------------- 1 | ## Examples 2 | 3 | ### Importing external files 4 | > `helpers.gs` 5 | ```glsl 6 | function add(number x, number y) { 7 | return x + y; 8 | } 9 | ``` 10 | > `main.gs` 11 | ```glsl 12 | import "helpers.gs" as helpers 13 | 14 | number value = helpers.add(5, 3); 15 | 16 | print(value); 17 | ``` 18 | 19 | ### Matrix math 20 | ```glsl 21 | number w = 640; 22 | number h = 480; 23 | number aspect = w / h; 24 | 25 | mat4 model = identity(); 26 | mat4 view = identity(); 27 | mat4 projection = perspective(radians(60.0), aspect, 0.1, 100.0); 28 | 29 | mat4 mvp = projection * view * model; 30 | 31 | vec3 point = vec3(1, 2, 3); 32 | vec4 p = mvp * vec4(point.xyz, 1); 33 | ``` 34 | 35 | ### Writing a file 36 | ```glsl 37 | file f = file.open("test.txt", "w+"); 38 | 39 | f.write("hello!"); 40 | 41 | f.close(); 42 | ``` 43 | 44 | ### Reading a file 45 | ```glsl 46 | file f = file.open("bible.txt", "r+"); 47 | 48 | iterator it = f.readLines(); 49 | 50 | while (string x = it.next()) { 51 | print(x); 52 | } 53 | 54 | f.close(); 55 | ``` 56 | 57 | ### Struct with function 58 | ```glsl 59 | typedef struct { 60 | function bark() { 61 | print("Woof woof!"); 62 | } 63 | } Dog; 64 | 65 | Dog dog = Dog(); 66 | 67 | dog.bark(); 68 | ``` 69 | 70 | ### Struct and `self` keyword 71 | ```glsl 72 | typedef struct { 73 | string name; 74 | 75 | function changeName(string newName) { 76 | self.name = newName; 77 | } 78 | } Person; 79 | 80 | 81 | Person p = Person("John Doe"); 82 | 83 | print(p.name); 84 | 85 | p.changeName("David Doe"); 86 | 87 | print(p.name); 88 | ``` 89 | 90 | ### Arbitrary objects 91 | ```glsl 92 | object x = { 93 | "hello": 123, 94 | "nested": { 95 | "yo": 42, 96 | "other": { 97 | name: "John" 98 | } 99 | } 100 | }; 101 | 102 | x.hello = 33; 103 | number y = x.hello; 104 | print(y); 105 | print(x.nested.other.name); 106 | ``` 107 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 | ### Generalized Linear Model Script 6 | > A scripting language focused on linear algebra, heavily inspired by [GLSL](https://en.wikipedia.org/wiki/OpenGL_Shading_Language) 7 | > and [JavaScript](https://en.wikipedia.org/wiki/JavaScript). 8 | 9 | > This language comes with types, functions and structures commonly used when doing linear algebra, 10 | > such as: `vec2`, `vec3`, `vec4`, `dot`, `cross`, `lerp`, `sin`, `cos` ...etc 11 | 12 | > (There are more to come, and everything is not implemented yet). 13 | 14 | ### Caution :warning: 15 | > This is a work in progress! 16 | 17 | ### Building & using it :hammer: 18 | ```bash 19 | mkdir build 20 | cd build 21 | cmake .. && make -j8 22 | 23 | ./glms_e 24 | ``` 25 | 26 | ## Extensions :electric_plug: 27 | > It's possible to create extensions for `GLMS`, 28 | > [here](https://github.com/sebbekarlsson/glms-canvas) is an example. 29 | > This specific extension let's you draw on a "canvas" using OpenGL. 30 | ```glsl 31 | import "libglms_canvas.so" as canvasLib; 32 | typedef (canvasLib.canvas) canvas; // we're making a "promise" to the interpreter 33 | // that this type will exist later. 34 | 35 | canvas c = canvas(640, 480); 36 | 37 | // opens a window, changes can be seen in real-time 38 | c.shade((vec3 uv, vec3 fragCoord, vec3 resolution, number time) => { 39 | return vec4(0.5 * (0.5 + cos(uv.x*time)), 0.5 * (0.5 + sin(uv.y * time)), cos(time), 1.0); 40 | }); 41 | ``` 42 | 43 | ## Documentation :open_book: 44 | > To see documentation, built-in functions etc, 45 | > Have a look at [this](docs/signatures.md) 46 | 47 | ## Integration 48 | > Want to integrate `GLMS` for scripting in an existing project? 49 | > Have a look at [this](docs/integration.md) 50 | 51 | ## Some interesting features :muscle: 52 | * `fetch` api, similar to the one in Javascript 53 | * `json` support 54 | * file IO 55 | * image manipulation 56 | * vector math 57 | * matrix math 58 | * almost all functions you'd see in `GLSL` exists in `GLMS` as well. 59 | * extension support (Extend the language by writing extensions) 60 | * ... and more 61 | 62 | 63 | ## Some examples :mag: 64 | 65 | ### Shader-like image manipulation 66 | ```glsl 67 | number w = 640; 68 | number h = 480; 69 | 70 | image img = image.make(w, h); 71 | 72 | img.shade((vec3 uv, vec3 fragCoord, vec3 resolution) => { 73 | vec3 center = resolution * 0.5; 74 | number d = abs(distance(fragCoord, center)); 75 | number g = 255 * (d < TAU * 6.0 * (1.0 + random())); 76 | vec3 color = mix(vec3(0.1, 0.3, 0.9), vec3(1), g); 77 | return vec4(color.xyz, 1.0); 78 | }); 79 | 80 | img.save("test.png"); 81 | ``` 82 | 83 | ### Functional programming 84 | ```glsl 85 | array arr = [1, 2, 3]; 86 | 87 | array mapped = arr.map((number v) => v * 2); 88 | 89 | print(mapped); // [2.000000, 4.000000, 6.000000] 90 | ``` 91 | 92 | ### Vectors 93 | ```glsl 94 | vec3 a = vec3(1, 0, 0); 95 | vec3 b = vec3(0, 1, 0); 96 | vec3 c = cross(a, b); 97 | 98 | print(c); 99 | 100 | vec3 d = vec3(random(), random(), random()); 101 | 102 | vec3 e = vec3(random(), random(), random()); 103 | 104 | print(distance(d, e)); 105 | 106 | vec3 f = vec3(random()); 107 | 108 | print(f); 109 | 110 | number dp = dot(d, f); 111 | 112 | print(dp); 113 | ``` 114 | 115 | ### Lerp 116 | ```glsl 117 | number x = 25.012; 118 | number y = 98.241; 119 | 120 | number z = lerp(x, y, 0.1); 121 | 122 | print(z); // 32.334900 123 | ``` 124 | 125 | ### Clamp 126 | ```glsl 127 | number value = 2312.0; 128 | value = clamp(value, 0.0, 1.0); 129 | print(value); // 1.000000 130 | ``` 131 | 132 | ### Structs 133 | ```glsl 134 | typedef struct { 135 | number age; 136 | string name; 137 | } Person; 138 | 139 | Person p = Person(33, "John Doe"); 140 | 141 | print(p.age); // 33.000000 142 | print(p.name); // John Doe 143 | ``` 144 | 145 | ### HTTP Requests 146 | ```glsl 147 | response r = fetch("https://example.org") 148 | 149 | print(r.status()) // 200 150 | print(r.text()) // prints the whole response text 151 | 152 | // we can also request json API's 153 | response r = fetch("https://jsonplaceholder.typicode.com/posts"); 154 | 155 | array p = r.json(); 156 | 157 | object firstPost = p[0]; 158 | 159 | print(firstPost.title); 160 | ``` 161 | 162 | ### Reading JSON 163 | ```glsl 164 | file f = file.open("assets/somefile.json", "r"); 165 | string contents = f.read(); 166 | f.close(); 167 | 168 | object data = json.parse(contents); 169 | 170 | print(data.firstName); 171 | print(data.age); 172 | ``` 173 | 174 | ### Template strings 175 | ```glsl 176 | string name = "John"; 177 | string x = `hello ${name}`; 178 | 179 | print(x); // hello John 180 | ``` 181 | 182 | ### More examples 183 | > For more examples, see [examples](EXAMPLES.md) 184 | 185 | ## FAQ 186 | 187 | ### Q: Why did you create this language? 188 | > I was looking for a scripting-language to be used in a game I was developing, 189 | > and I wanted something that came with vector operatons right out of the box (just like GLSL), but I also 190 | > wanted it to be expressive like Javascript. 191 | 192 | ### Q: How do I integrate it into my application / game ? 193 | > Have a look at [this](docs/integration.md) 194 | > If it's still not clear, feel free to create an issue or something with your question. 195 | 196 | ### Q: What operating systems / platforms can this language run on? 197 | > It will most likely only work on Linux right now (maybe MacOS as well), but 198 | > you're always welcome to contribute to support more platforms! 199 | 200 | ### Q: Any other plans for this language? 201 | > It would be cool to add some frontends to the language, here's some I've had in mind: 202 | 203 | * GLSL - Would be cool to use this as a transpiler for GLSL 204 | * Javascript - Emitting Javascript would allow for web-applications being created with GLMS 205 | * WASM - Same reason as the Javascript one 206 | * 64bit assembly - Because it's cool :sunglasses: 207 | 208 | > That being said, I'm not sure I'd ever implement any of these ideas. 209 | > I'm just using this for scripting a game I'm developing at the moment. 210 | 211 | ### Q: Is there some kind of community? 212 | > I just threw together a Discord-server for whoever is interested, you can find it [here](https://discord.gg/tUWNHySs) 213 | 214 | ### Q: Can I contribute? 215 | > Please do! Simply fork and create pull-requests :fire: 216 | 217 | ## Syntax highlighting 218 | * [glms-mode for emacs](https://github.com/sebbekarlsson/glms-mode) 219 | -------------------------------------------------------------------------------- /changelog.md: -------------------------------------------------------------------------------- 1 | > 8a6513be1e4be395d71ddb82afcd8bc5eef6c99e (HEAD -> master, origin/master, origin/HEAD) adds floor() ceil() round() 2 | -------------------------------------------------------------------------------- /cmake/modules/glms_deps.cmake: -------------------------------------------------------------------------------- 1 | macro (glms_get_dep DEP_NAME DEP_URL) 2 | set (extra_args ${ARGN}) 3 | list(LENGTH extra_args extra_count) 4 | if (NOT TARGET ${DEP_NAME}) 5 | FetchContent_Declare( 6 | ${DEP_NAME} 7 | GIT_REPOSITORY ${DEP_URL} 8 | ) 9 | FetchContent_MakeAvailable(${DEP_NAME}) 10 | 11 | if (${extra_count} GREATER 0) 12 | list(GET extra_args 0 optional_arg) 13 | target_compile_options(${DEP_NAME} PUBLIC ${optional_arg}) 14 | endif () 15 | endif() 16 | endmacro() 17 | 18 | function (glms_deps TARGET_NAME) 19 | include(FetchContent) 20 | 21 | 22 | glms_get_dep(memo_static https://github.com/sebbekarlsson/memo.git) 23 | glms_get_dep(arena_static https://github.com/sebbekarlsson/arena.git) 24 | glms_get_dep(text_static https://github.com/sebbekarlsson/text.git) 25 | glms_get_dep(hashy_static https://github.com/sebbekarlsson/hashy.git) 26 | glms_get_dep(mif_static https://github.com/sebbekarlsson/mif.git) 27 | #glms_get_dep(vec3_static https://github.com/sebbekarlsson/vec3.git) 28 | glms_get_dep(fjson_static https://github.com/sebbekarlsson/fastjson.git) 29 | glms_get_dep(spath_static https://github.com/sebbekarlsson/spath.git -fPIC) 30 | glms_get_dep(gimg_static https://github.com/sebbekarlsson/gimg.git -fPIC) 31 | 32 | 33 | 34 | if (NOT TARGET cglm) 35 | FetchContent_Declare( 36 | cglm 37 | GIT_REPOSITORY https://github.com/recp/cglm.git 38 | GIT_TAG "v0.9.1" 39 | ) 40 | FetchContent_MakeAvailable(cglm) 41 | endif() 42 | 43 | 44 | if (NOT TARGET curl AND NOT TARGET curl_lib) 45 | 46 | find_library(CURL_LIB curl) 47 | 48 | if (NOT CURL_LIB) 49 | FetchContent_Declare( 50 | curl_lib 51 | GIT_REPOSITORY https://github.com/curl/curl.git 52 | GIT_TAG "curl-7_87_0" 53 | ) 54 | FetchContent_MakeAvailable(curl_lib) 55 | include_directories(${curl_lib_INCLUDE_DIRECTORIES}) 56 | message(${curl_lib_INCLUDE_DIRECTORIES}) 57 | endif() 58 | endif() 59 | 60 | 61 | 62 | set(GLMS_DEPS m gimg_static memo_static arena_static hashy_static text_static mif_static spath_static fjson_static cglm curl dl) 63 | 64 | target_link_libraries(${TARGET_NAME} ${GLMS_DEPS}) 65 | endfunction() 66 | -------------------------------------------------------------------------------- /docs/integration.md: -------------------------------------------------------------------------------- 1 | # Integration 2 | > The reason this language was created was to use it in a game engine. 3 | > So the following examples will cover this. 4 | 5 | ## Example 6 | > Let's say you have a struct in your project that looks like this: 7 | ```C 8 | // could also be a class, or anything really. 9 | typedef struct { 10 | Vector3 position; 11 | } GameObject; 12 | ``` 13 | > And you want to use GLMS to manipulate an instance of this object somehow. 14 | > Here's how you would do this: 15 | ```C 16 | #include 17 | #include 18 | 19 | typedef struct { 20 | Vector3 position; 21 | } GameObject; 22 | 23 | 24 | // function to get position 25 | int game_object_fptr_get_position(GLMSEval *eval, GLMSAST *self, 26 | GLMSASTBuffer* args, GLMSStack* stack, 27 | GLMSAST *out) { 28 | 29 | GameObject* obj = (GameObject*)self->ptr; // `ptr` is basically free real-estate, you can assign whatever you want to it. 30 | // here we already have assigned an instance of `GameObject` to it. 31 | 32 | *out = (GLMSAST){ .type = GLMS_AST_TYPE_VEC3, .as.v3 = obj->position }; // we return a vec3 33 | 34 | return 1; // 1 indicates success 35 | } 36 | 37 | // function to modify & set position 38 | int game_object_fptr_set_position(GLMSEval *eval, GLMSAST *self, 39 | GLMSASTBuffer* args, GLMSStack* stack, 40 | GLMSAST *out) { 41 | 42 | if (!glms_eval_expect(eval, stack, (GLMSASTType[]){ GLMS_AST_TYPE_VEC3 }, 1, args)) return 0; // we expect to receive a vec3 43 | 44 | GameObject* obj = (GameObject*)self->ptr; // `ptr` is basically free real-estate, you can assign whatever you want to it. 45 | // here we already have assigned an instance of `GameObject` to it. 46 | 47 | obj->position = args->items[0].as.v3; // reassign value 48 | 49 | return 1; // 1 indicates success 50 | } 51 | 52 | // constructor for our type 53 | void game_object_fptr_constructor(GLMSEval *eval, GLMSStack *stack, 54 | GLMSASTBuffer *args, GLMSAST *self) { 55 | self->constructor = game_object_fptr_constructor; // make sure GLMS knows how to re-construct instances of this type. 56 | glms_ast_register_function(eval->env, self, "getPosition", game_object_fptr_get_position); 57 | glms_ast_register_function(eval->env, self, "setPosition", game_object_fptr_set_position); 58 | 59 | } 60 | 61 | // register our custom type 62 | void register_custom_types(GLMSEnv* env) { 63 | GLMSAST* my_type = glms_env_new_ast(env, GLMS_AST_TYPE_STRUCT, true); 64 | glms_env_register_type(env, "GameObject", my_type, game_object_fptr_constructor, 65 | 0, // swizzle, 66 | 0, // to_string, 67 | 0 // destructor 68 | ); 69 | 70 | } 71 | 72 | // expose an instance of our `GameObject` to the scripting environment 73 | void expose_game_object(GLMSEnv* env, GameObject* obj) { 74 | GLMSAST* instance = glms_env_new_ast(env, GLMS_AST_TYPE_STRUCT, true); 75 | instance->constructor = game_object_fptr_constructor; // Again, this is our way of letting GLMS know what type this is. 76 | // alternatively, you can also do this: 77 | // instance->typename = strdup("GameObject"); 78 | // and GLMS will automatically find the constructor for you. 79 | // but we can save some bytes here by not allocating a new string. 80 | 81 | 82 | instance->ptr = obj; // `ptr` is free real-estate, assign whatever you want to it. 83 | glms_env_register_any(env, "myobj", instance); // will be available as a global variable called "myobj" 84 | } 85 | 86 | // finally setup everything 87 | void some_place_in_your_project_where_setting_up_the_scripting_environment_is_appropriate() { 88 | GLMSEnv env = {0}; 89 | const char* source_code = get_source_code_of_script_from_somewhere(); 90 | glms_env_init( 91 | &env, 92 | source_code, // source code of script 93 | "path/to/where/source/code/originates", // this is optional, put a `0` if you don't want to use this. 94 | // It's used to have the scripting environment more intelligently 95 | // find "import" paths. 96 | (GLMSConfig){0} // configuration for environment, 97 | // currently this can only be empty. 98 | ); 99 | 100 | 101 | 102 | GameObject* obj = get_this_object_from_somewhere_maybe_malloc(); 103 | 104 | register_custom_types(&env); 105 | expose_game_object(&env, obj); 106 | 107 | // later execute the script by running 108 | glms_env_exec(&env); 109 | 110 | 111 | // when you're done, run: 112 | glms_env_clear(&env); 113 | // however, this will clear all defined variables etc. 114 | // so if your intention is to maintain the state during multiple calls, 115 | // don't call this until you're `truly` done. 116 | } 117 | ``` 118 | 119 | > Now, in `GLMS`; you will be able to do something like this: 120 | ```glsl 121 | vec3 pos = myobj.getPosition(); 122 | print(pos); 123 | myobj.setPosition(vec3(3, 1.13, 1.6)); 124 | ``` 125 | 126 | ## More examples of integration 127 | > For a better understanding, or for more examples; have a look [here](https://github.com/sebbekarlsson/glms/tree/master/src/modules). 128 | > [this](https://github.com/sebbekarlsson/glms/blob/d4dcf3039fd4a0f4154ee04ee69653f5966f194e/src/builtin.c#L596) might also be of interest. 129 | > In these files you can see how types, functions, globals, etc are currently implemented into the language. 130 | > The same principles can be applied when integrating this language in any other project. 131 | -------------------------------------------------------------------------------- /docs/signatures.md: -------------------------------------------------------------------------------- 1 | ## Global functions 2 | 3 | ### unit 4 | ``` 5 | GLMS_AST_TYPE_VEC3 unit(GLMS_AST_TYPE_VEC3) 6 | 7 | ``` 8 | 9 | ### ceil 10 | ``` 11 | GLMS_AST_TYPE_NUMBER ceil(GLMS_AST_TYPE_NUMBER) 12 | 13 | ``` 14 | 15 | ### cantor 16 | ``` 17 | GLMS_AST_TYPE_NUMBER cantor(GLMS_AST_TYPE_NUMBER, GLMS_AST_TYPE_NUMBER) 18 | 19 | ``` 20 | 21 | ### transpose 22 | ``` 23 | GLMS_AST_TYPE_MAT4 transpose(GLMS_AST_TYPE_MAT4) 24 | 25 | ``` 26 | 27 | ### clamp 28 | ``` 29 | GLMS_AST_TYPE_NUMBER clamp(GLMS_AST_TYPE_NUMBER value, GLMS_AST_TYPE_NUMBER min, GLMS_AST_TYPE_NUMBER max) 30 | 31 | ``` 32 | 33 | ### perspective 34 | ``` 35 | GLMS_AST_TYPE_MAT4 perspective(GLMS_AST_TYPE_NUMBER fov, GLMS_AST_TYPE_NUMBER aspect, GLMS_AST_TYPE_NUMBER near, GLMS_AST_TYPE_NUMBER far) 36 | 37 | ``` 38 | 39 | ### exit 40 | > No signatures defined. 41 | 42 | 43 | ### cross 44 | ``` 45 | GLMS_AST_TYPE_VEC3 cross(GLMS_AST_TYPE_VEC3, GLMS_AST_TYPE_VEC3) 46 | 47 | ``` 48 | 49 | ### atan 50 | ``` 51 | GLMS_AST_TYPE_NUMBER atan(GLMS_AST_TYPE_NUMBER) 52 | GLMS_AST_TYPE_NUMBER atan(GLMS_AST_TYPE_NUMBER, GLMS_AST_TYPE_NUMBER) 53 | 54 | ``` 55 | 56 | ### log 57 | ``` 58 | GLMS_AST_TYPE_NUMBER log(GLMS_AST_TYPE_NUMBER) 59 | 60 | ``` 61 | 62 | ### trace 63 | > No signatures defined. 64 | 65 | 66 | ### fract 67 | ``` 68 | GLMS_AST_TYPE_NUMBER fract(GLMS_AST_TYPE_NUMBER) 69 | 70 | ``` 71 | 72 | ### dot 73 | ``` 74 | GLMS_AST_TYPE_NUMBER dot(GLMS_AST_TYPE_VEC3, GLMS_AST_TYPE_VEC3) 75 | 76 | ``` 77 | 78 | ### min 79 | ``` 80 | GLMS_AST_TYPE_NUMBER min(GLMS_AST_TYPE_NUMBER, GLMS_AST_TYPE_NUMBER) 81 | 82 | ``` 83 | 84 | ### sin 85 | ``` 86 | GLMS_AST_TYPE_NUMBER sin(GLMS_AST_TYPE_NUMBER) 87 | 88 | ``` 89 | 90 | ### pow 91 | ``` 92 | GLMS_AST_TYPE_NUMBER pow(GLMS_AST_TYPE_NUMBER, GLMS_AST_TYPE_NUMBER) 93 | 94 | ``` 95 | 96 | ### mix 97 | ``` 98 | GLMS_AST_TYPE_NUMBER mix(GLMS_AST_TYPE_NUMBER from, GLMS_AST_TYPE_NUMBER to, GLMS_AST_TYPE_NUMBER scale) 99 | GLMS_AST_TYPE_VEC3 mix(GLMS_AST_TYPE_VEC3 from, GLMS_AST_TYPE_VEC3 to, GLMS_AST_TYPE_NUMBER scale) 100 | 101 | ``` 102 | 103 | ### max 104 | ``` 105 | GLMS_AST_TYPE_NUMBER max(GLMS_AST_TYPE_NUMBER, GLMS_AST_TYPE_NUMBER) 106 | 107 | ``` 108 | 109 | ### decant 110 | ``` 111 | GLMS_AST_TYPE_ARRAY decant(GLMS_AST_TYPE_NUMBER) 112 | 113 | ``` 114 | 115 | ### log10 116 | ``` 117 | GLMS_AST_TYPE_NUMBER log10(GLMS_AST_TYPE_NUMBER) 118 | 119 | ``` 120 | 121 | ### radians 122 | ``` 123 | GLMS_AST_TYPE_NUMBER radians(GLMS_AST_TYPE_NUMBER) 124 | 125 | ``` 126 | 127 | ### abs 128 | ``` 129 | GLMS_AST_TYPE_NUMBER abs(GLMS_AST_TYPE_NUMBER) 130 | 131 | ``` 132 | 133 | ### identity 134 | ``` 135 | GLMS_AST_TYPE_MAT4 identity() 136 | 137 | ``` 138 | 139 | ### quit 140 | > No signatures defined. 141 | 142 | 143 | ### random 144 | ``` 145 | GLMS_AST_TYPE_NUMBER random() // Returns a random value between 0 and 1. 146 | 147 | GLMS_AST_TYPE_NUMBER random(GLMS_AST_TYPE_NUMBER min, GLMS_AST_TYPE_NUMBER max) 148 | GLMS_AST_TYPE_NUMBER random(GLMS_AST_TYPE_NUMBER min, GLMS_AST_TYPE_NUMBER max, GLMS_AST_TYPE_NUMBER seed) 149 | 150 | ``` 151 | 152 | ### cos 153 | ``` 154 | GLMS_AST_TYPE_NUMBER cos(GLMS_AST_TYPE_NUMBER) 155 | 156 | ``` 157 | 158 | ### floor 159 | ``` 160 | GLMS_AST_TYPE_NUMBER floor(GLMS_AST_TYPE_NUMBER) 161 | 162 | ``` 163 | 164 | ### round 165 | ``` 166 | GLMS_AST_TYPE_NUMBER round(GLMS_AST_TYPE_NUMBER) 167 | 168 | ``` 169 | 170 | ### quatFor 171 | ``` 172 | GLMS_AST_TYPE_VEC4 quatFor(GLMS_AST_TYPE_VEC4 dir, GLMS_AST_TYPE_VEC4 up) 173 | 174 | ``` 175 | 176 | ### tan 177 | ``` 178 | GLMS_AST_TYPE_NUMBER tan(GLMS_AST_TYPE_NUMBER) 179 | 180 | ``` 181 | 182 | ### normalize 183 | ``` 184 | GLMS_AST_TYPE_VEC3 normalize(GLMS_AST_TYPE_VEC3) 185 | 186 | ``` 187 | 188 | ### dump 189 | > No signatures defined. 190 | 191 | 192 | ### distance 193 | ``` 194 | GLMS_AST_TYPE_NUMBER distance(GLMS_AST_TYPE_VEC3, GLMS_AST_TYPE_VEC3) 195 | 196 | ``` 197 | 198 | ### length 199 | ``` 200 | GLMS_AST_TYPE_NUMBER length(GLMS_AST_TYPE_VEC3) 201 | GLMS_AST_TYPE_NUMBER length(GLMS_AST_TYPE_STRING) 202 | GLMS_AST_TYPE_NUMBER length(GLMS_AST_TYPE_ARRAY) 203 | 204 | ``` 205 | 206 | ### print 207 | > No signatures defined. 208 | 209 | 210 | ### inverse 211 | ``` 212 | GLMS_AST_TYPE_MAT4 inverse(GLMS_AST_TYPE_MAT4) 213 | 214 | ``` 215 | 216 | ### lerp 217 | ``` 218 | GLMS_AST_TYPE_NUMBER lerp(GLMS_AST_TYPE_NUMBER from, GLMS_AST_TYPE_NUMBER to, GLMS_AST_TYPE_NUMBER scale) 219 | GLMS_AST_TYPE_VEC3 lerp(GLMS_AST_TYPE_VEC3 from, GLMS_AST_TYPE_VEC3 to, GLMS_AST_TYPE_NUMBER scale) 220 | 221 | ``` 222 | 223 | ### ortho 224 | ``` 225 | GLMS_AST_TYPE_MAT4 ortho(GLMS_AST_TYPE_NUMBER left, GLMS_AST_TYPE_NUMBER right, GLMS_AST_TYPE_NUMBER bottom, GLMS_AST_TYPE_NUMBER top, GLMS_AST_TYPE_NUMBER near, GLMS_AST_TYPE_NUMBER far) 226 | 227 | ``` 228 | 229 | ### smoothstep 230 | ``` 231 | GLMS_AST_TYPE_NUMBER smoothstep(GLMS_AST_TYPE_NUMBER edge0, GLMS_AST_TYPE_NUMBER edge1, GLMS_AST_TYPE_NUMBER value) 232 | GLMS_AST_TYPE_VEC3 smoothstep(GLMS_AST_TYPE_VEC3 edge0, GLMS_AST_TYPE_VEC3 edge1, GLMS_AST_TYPE_NUMBER value) 233 | GLMS_AST_TYPE_VEC3 smoothstep(GLMS_AST_TYPE_VEC3 edge0, GLMS_AST_TYPE_VEC3 edge1, GLMS_AST_TYPE_VEC3 value) 234 | 235 | ``` 236 | 237 | ### fetch 238 | ``` 239 | response fetch(GLMS_AST_TYPE_STRING URL) 240 | 241 | ``` 242 | 243 | ## Types & structures 244 | 245 | ### string (struct) 246 |
props 247 | 248 | ### string.includes 249 | ``` 250 | GLMS_AST_TYPE_BOOL string.includes(GLMS_AST_TYPE_STRING needle) 251 | 252 | ``` 253 | 254 | ### string.replace 255 | ``` 256 | GLMS_AST_TYPE_STRING string.replace(GLMS_AST_TYPE_STRING pattern, GLMS_AST_TYPE_STRING replacement) 257 | 258 | ``` 259 | 260 | 261 |
262 | 263 | 264 | ### array (struct) 265 |
props 266 | 267 | ### array.push 268 | > No signatures defined. 269 | 270 | 271 | ### array.map 272 | > No signatures defined. 273 | 274 | 275 | ### array.sort 276 | > No signatures defined. 277 | 278 | 279 | ### array.includes 280 | > No signatures defined. 281 | 282 | 283 | ### array.count 284 | > No signatures defined. 285 | 286 | 287 | ### array.filter 288 | > No signatures defined. 289 | 290 | 291 | ### array.length 292 | > No signatures defined. 293 | 294 | 295 | 296 |
297 | 298 | 299 | ### image (struct) 300 |
props 301 | 302 | ### image.save 303 | ``` 304 | GLMS_AST_TYPE_BOOL image.save(GLMS_AST_TYPE_STRING filename) 305 | 306 | ``` 307 | 308 | ### image.setPixel 309 | ``` 310 | GLMS_AST_TYPE_VOID image.setPixel(GLMS_AST_TYPE_VEC4 pixel) 311 | 312 | ``` 313 | 314 | ### image.getPixel 315 | ``` 316 | GLMS_AST_TYPE_VEC4 image.getPixel(GLMS_AST_TYPE_NUMBER x, GLMS_AST_TYPE_NUMBER y) 317 | 318 | ``` 319 | 320 | ### image.load 321 | ``` 322 | GLMS_AST_TYPE_STRUCT image.load(GLMS_AST_TYPE_STRING) 323 | 324 | ``` 325 | 326 | ### image.shade 327 | ``` 328 | GLMS_AST_TYPE_BOOL image.shade(GLMS_AST_TYPE_FUNC) 329 | 330 | ``` 331 | 332 | ### image.make 333 | ``` 334 | image image.make(GLMS_AST_TYPE_NUMBER width, GLMS_AST_TYPE_NUMBER height) 335 | 336 | ``` 337 | 338 | 339 |
340 | 341 | 342 | ### vec3 (struct) 343 | 344 | ### vec4 (struct) 345 | 346 | ### response (struct) 347 |
props 348 | 349 | ### response.data 350 | > No signatures defined. 351 | 352 | 353 | ### response.text 354 | > No signatures defined. 355 | 356 | 357 | ### response.json 358 | > No signatures defined. 359 | 360 | 361 | ### response.status 362 | > No signatures defined. 363 | 364 | 365 | 366 |
367 | 368 | 369 | ### iterator (struct) 370 |
props 371 | 372 | ### iterator.next 373 | > No signatures defined. 374 | 375 | 376 | 377 |
378 | 379 | 380 | ### json (struct) 381 |
props 382 | 383 | ### json.stringify 384 | ``` 385 | GLMS_AST_TYPE_STRING json.stringify(GLMS_AST_TYPE_OBJECT) 386 | 387 | ``` 388 | 389 | ### json.parse 390 | ``` 391 | GLMS_AST_TYPE_OBJECT json.parse(GLMS_AST_TYPE_STRING jsonString) 392 | 393 | ``` 394 | 395 | 396 |
397 | 398 | 399 | ### mat4 (struct) 400 | 401 | ### file (struct) 402 |
props 403 | 404 | ### file.read 405 | > No signatures defined. 406 | 407 | 408 | ### file.write 409 | ``` 410 | GLMS_AST_TYPE_BOOL file.write(GLMS_AST_TYPE_STRING text) 411 | 412 | ``` 413 | 414 | ### file.open 415 | ``` 416 | file file.open(GLMS_AST_TYPE_STRING filename, GLMS_AST_TYPE_STRING mode) 417 | 418 | ``` 419 | 420 | ### file.close 421 | ``` 422 | GLMS_AST_TYPE_BOOL file.close() 423 | 424 | ``` 425 | 426 | ### file.readLines 427 | ``` 428 | GLMS_AST_TYPE_ITERATOR file.readLines() 429 | 430 | ``` 431 | 432 | 433 |
434 | 435 | 436 | -------------------------------------------------------------------------------- /glms.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sebbekarlsson/glms/bcd54bccd237965cdd341055cc845768309d0177/glms.png -------------------------------------------------------------------------------- /include/glms/allocator.h: -------------------------------------------------------------------------------- 1 | #ifndef GLMS_ALLOCATOR_H 2 | #define GLMS_ALLOCATOR_H 3 | #include 4 | 5 | typedef void* (*GLMSAllocatorFunc)(void* user_ptr, int64_t size); 6 | typedef char* (*GLMSAllocatorStrdup)(void* user_ptr, const char* str); 7 | 8 | typedef void (*GLMSAllocatorStrcat)(void* user_ptr, char** instr, 9 | const char* append); 10 | 11 | typedef struct { 12 | void* user_ptr; 13 | GLMSAllocatorFunc func; 14 | GLMSAllocatorStrdup strdup; 15 | GLMSAllocatorStrcat strcat; 16 | } GLMSAllocator; 17 | 18 | void glms_allocator_string_allocator(GLMSAllocator* alloc); 19 | #endif 20 | -------------------------------------------------------------------------------- /include/glms/ast.h: -------------------------------------------------------------------------------- 1 | #ifndef GLMS_AST_H 2 | #define GLMS_AST_H 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #define GLMS_AST_OPERATOR_OVERLOAD_CAP 24 23 | 24 | struct GLMS_ENV_STRUCT; 25 | struct GLMS_EVAL_STRUCT; 26 | struct GLMS_STACK_STRUCT; 27 | 28 | struct GLMS_BUFFER_GLMSAST; 29 | struct GLMS_GLMSAST_LIST_STRUCT; 30 | 31 | struct GLMS_AST_STRUCT; 32 | 33 | #define JAST struct GLMS_AST_STRUCT 34 | 35 | typedef void (*GLMSASTContructor)(struct GLMS_EVAL_STRUCT* eval, 36 | struct GLMS_STACK_STRUCT* stack, 37 | struct GLMS_BUFFER_GLMSAST* args, 38 | struct GLMS_AST_STRUCT* self); 39 | 40 | typedef int (*GLMSASTSwizzle)(struct GLMS_EVAL_STRUCT* eval, 41 | struct GLMS_STACK_STRUCT* stack, 42 | struct GLMS_AST_STRUCT* ast, 43 | struct GLMS_AST_STRUCT* accessor, 44 | struct GLMS_AST_STRUCT* out); 45 | 46 | typedef char* (*GLMSASTToString)(struct GLMS_AST_STRUCT* ast, 47 | GLMSAllocator alloc, 48 | struct GLMS_ENV_STRUCT* env); 49 | 50 | typedef void (*GLMSASTDestructor)(struct GLMS_AST_STRUCT* ast); 51 | 52 | typedef int (*GLMSASTAtomFunc)(struct GLMS_AST_STRUCT* ast, 53 | struct GLMS_BUFFER_GLMSAST* out); 54 | 55 | typedef int (*GLMSASTOperatorOverload)(struct GLMS_EVAL_STRUCT* eval, 56 | struct GLMS_STACK_STRUCT* stack, 57 | struct GLMS_AST_STRUCT* left, 58 | struct GLMS_AST_STRUCT* right, 59 | struct GLMS_AST_STRUCT* out); 60 | 61 | typedef enum { 62 | GLMS_AST_NUMBER_TYPE_FLOAT, 63 | GLMS_AST_NUMBER_TYPE_INT, 64 | GLMS_AST_NUMBER_TYPE_UINT64 65 | } GLMSASTNumberType; 66 | 67 | typedef struct GLMS_AST_STRUCT { 68 | union { 69 | struct { 70 | float value; 71 | int value_int; 72 | uint64_t value_uint64; 73 | GLMSASTNumberType type; 74 | } number; 75 | 76 | struct { 77 | struct GLMS_AST_STRUCT* id; 78 | } fdecl; 79 | 80 | struct { 81 | GLMSStringView value; 82 | GLMSTokenType op; 83 | char* heap; 84 | } id; 85 | 86 | struct { 87 | GLMSStringView value; 88 | JAST* id; 89 | } import; 90 | 91 | struct { 92 | GLMSStringView value; 93 | } include; 94 | 95 | struct { 96 | struct GLMS_AST_STRUCT* right; 97 | } layout; 98 | 99 | struct { 100 | JAST* factor; 101 | JAST* id; 102 | } tdef; 103 | 104 | struct { 105 | GLMSStringView value; 106 | char* heap; 107 | } string; 108 | 109 | struct { 110 | struct GLMS_AST_STRUCT* right; 111 | } raw_glsl; 112 | 113 | struct { 114 | char c; 115 | } character; 116 | 117 | struct { 118 | GLMSTokenType op; 119 | JAST* left; 120 | JAST* right; 121 | } binop; 122 | 123 | struct { 124 | JAST* left; 125 | JAST* right; 126 | JAST* func; 127 | } call; 128 | 129 | struct { 130 | JAST* left; 131 | JAST* right; 132 | } access; 133 | 134 | struct { 135 | JAST* id; 136 | JAST* body; 137 | char* name; 138 | GLMSFunctionSignatureBuffer signatures; 139 | } func; 140 | 141 | struct { 142 | JAST* body; 143 | } forloop; 144 | 145 | struct { 146 | GLMSTokenType op; 147 | JAST* right; 148 | JAST* left; 149 | } unop; 150 | 151 | struct { 152 | GLMSTokenType op; 153 | JAST* body; 154 | JAST* expr; 155 | JAST* next; 156 | } block; 157 | 158 | struct { 159 | JAST* condition; 160 | JAST* expr1; 161 | JAST* expr2; 162 | } ternary; 163 | 164 | struct { 165 | struct GLMS_ENV_STRUCT* env; 166 | } stack; 167 | 168 | struct { 169 | GLMSIterator it; 170 | void* state; 171 | } iterator; 172 | 173 | struct { 174 | int idx; 175 | JAST* ptr; 176 | } stackptr; 177 | 178 | bool boolean; 179 | 180 | Vector2 v2; 181 | Vector3 v3; 182 | Vector4 v4; 183 | 184 | mat3s m3; 185 | mat4s m4; 186 | 187 | } as; 188 | 189 | GLMSASTType type; 190 | HashyMap props; 191 | struct GLMS_GLMSAST_LIST_STRUCT* children; 192 | struct GLMS_GLMSAST_LIST_STRUCT* flags; 193 | GLMSASTOperatorOverload op_overloads[GLMS_AST_OPERATOR_OVERLOAD_CAP]; 194 | GLMSFPTR fptr; 195 | JSON* json; 196 | void* ptr; 197 | char* string_rep; 198 | GLMSASTContructor constructor; 199 | GLMSASTSwizzle swizzle; 200 | GLMSASTToString to_string; 201 | GLMSASTDestructor destructor; 202 | GLMSASTAtomFunc get_atoms; 203 | GLMSIteratorNext iterator_next; 204 | char* typename; 205 | JAST* value_type; 206 | JAST* result; 207 | float* floats; 208 | ArenaRef ref; 209 | bool keep; 210 | bool is_tmp; 211 | bool is_heap; 212 | bool constructed; 213 | bool is_reserved; 214 | struct GLMS_ENV_STRUCT* env_ref; 215 | } GLMSAST; 216 | 217 | GLMS_DEFINE_BUFFER(GLMSAST); 218 | GLMS_DEFINE_LIST(GLMSAST); 219 | 220 | GLMSAST* glms_ast_push(GLMSAST* parent, GLMSAST* child); 221 | GLMSAST* glms_ast_push_flag(GLMSAST* parent, GLMSAST* flag); 222 | 223 | bool glms_ast_is_iterable(GLMSAST* ast); 224 | 225 | int glms_ast_iterate(struct GLMS_ENV_STRUCT* env, GLMSAST* ast, 226 | GLMSIterator* it, GLMSAST* out); 227 | 228 | const char* glms_ast_get_name(GLMSAST* ast); 229 | 230 | const char* glms_ast_get_string_value(GLMSAST* ast); 231 | 232 | char* glms_ast_to_string(GLMSAST ast, GLMSAllocator alloc, 233 | struct GLMS_ENV_STRUCT* env); 234 | 235 | bool glms_ast_is_truthy(GLMSAST ast); 236 | 237 | bool glms_ast_compare_equals_equals(GLMSAST a, GLMSAST b); 238 | bool glms_ast_compare_gt(GLMSAST a, GLMSAST b); 239 | bool glms_ast_compare_gte(GLMSAST a, GLMSAST b); 240 | bool glms_ast_compare_lt(GLMSAST a, GLMSAST b); 241 | bool glms_ast_compare_lte(GLMSAST a, GLMSAST b); 242 | 243 | float glms_ast_get_number_by_key(GLMSAST* ast, const char* key); 244 | 245 | GLMSAST* glms_ast_object_set_property(GLMSAST* obj, const char* key, 246 | GLMSAST* value); 247 | 248 | GLMSAST* glms_ast_access_by_index(GLMSAST* ast, int64_t index, 249 | struct GLMS_ENV_STRUCT* env); 250 | GLMSAST* glms_ast_access_by_key(GLMSAST* ast, const char* key, 251 | struct GLMS_ENV_STRUCT* env); 252 | 253 | int64_t glms_ast_array_get_length(GLMSAST* ast); 254 | 255 | int glms_ast_get_type(GLMSAST ast, GLMSAST* out); 256 | 257 | GLMSAST* glms_ast_copy(GLMSAST src, struct GLMS_ENV_STRUCT* env); 258 | 259 | void glms_ast_destructor(GLMSAST* ast); 260 | 261 | bool glms_ast_is_vector(GLMSAST* ast); 262 | 263 | void glms_ast_keep(GLMSAST* ast); 264 | 265 | GLMSAST* glms_ast_get_property(GLMSAST* ast, const char* key); 266 | 267 | GLMSAST* glms_ast_register_function(struct GLMS_ENV_STRUCT* env, GLMSAST* ast, 268 | const char* name, GLMSFPTR fptr); 269 | 270 | GLMSAST glms_ast_op_add_add(GLMSAST* a); 271 | GLMSAST glms_ast_op_sub_sub(GLMSAST* a); 272 | 273 | GLMSAST glms_ast_op_add(GLMSAST a, GLMSAST b); 274 | GLMSAST glms_ast_op_add_eq(GLMSAST* a, GLMSAST b); 275 | GLMSAST glms_ast_op_sub_eq(GLMSAST* a, GLMSAST b); 276 | GLMSAST glms_ast_op_mul_eq(GLMSAST* a, GLMSAST b); 277 | GLMSAST glms_ast_op_div_eq(GLMSAST* a, GLMSAST b); 278 | 279 | GLMSAST glms_ast_op_sub(GLMSAST a, GLMSAST b); 280 | GLMSAST glms_ast_op_mul(GLMSAST a, GLMSAST b); 281 | GLMSAST glms_ast_op_mod(GLMSAST a, GLMSAST b); 282 | GLMSAST glms_ast_op_div(GLMSAST a, GLMSAST b); 283 | GLMSAST glms_ast_op_eq(GLMSAST a, GLMSAST b); 284 | GLMSAST glms_ast_op_and_and(GLMSAST a, GLMSAST b); 285 | GLMSAST glms_ast_op_pipe_pipe(GLMSAST a, GLMSAST b); 286 | GLMSAST glms_ast_op_lt(GLMSAST a, GLMSAST b); 287 | GLMSAST glms_ast_op_gt(GLMSAST a, GLMSAST b); 288 | GLMSAST glms_ast_op_lte(GLMSAST a, GLMSAST b); 289 | GLMSAST glms_ast_op_gte(GLMSAST a, GLMSAST b); 290 | GLMSAST glms_ast_assign(GLMSAST* a, GLMSAST b, struct GLMS_EVAL_STRUCT* eval, 291 | struct GLMS_STACK_STRUCT* stack); 292 | 293 | GLMSAST* glms_ast_get_ptr(GLMSAST a); 294 | 295 | GLMSAST* glms_ast_register_operator_overload(struct GLMS_ENV_STRUCT* env, 296 | GLMSAST* ast, GLMSTokenType op, 297 | GLMSASTOperatorOverload func); 298 | 299 | GLMSASTOperatorOverload glms_ast_get_op_overload(GLMSAST ast, GLMSTokenType op, 300 | struct GLMS_ENV_STRUCT* env); 301 | 302 | GLMSAST* glms_ast_register_func_overload(struct GLMS_ENV_STRUCT* env, 303 | GLMSAST* ast, const char* name, 304 | GLMSFPTR func); 305 | 306 | GLMSFPTR glms_ast_get_func_overload(GLMSAST ast, const char* name); 307 | 308 | float glms_ast_number(GLMSAST ast); 309 | 310 | char* glms_ast_to_string_debug(GLMSAST ast); 311 | 312 | typedef struct { 313 | bool have_detail; 314 | } GLMSDocstringGenerator; 315 | 316 | char* glms_ast_generate_docstring(GLMSAST ast, const char* name, 317 | const char* suffix, int depth, 318 | GLMSDocstringGenerator* gen); 319 | 320 | int glms_ast_get_atoms(GLMSAST ast, GLMSASTBuffer* out); 321 | 322 | GLMSAST* glms_ast_from_json(struct GLMS_ENV_STRUCT* env, JSON* v); 323 | 324 | #define GLMSAST_VALUE(ast) (ast->as.number.value) 325 | 326 | #endif 327 | -------------------------------------------------------------------------------- /include/glms/ast_type.h: -------------------------------------------------------------------------------- 1 | #ifndef GLMS_AST_TYPE_H 2 | #define GLMS_AST_TYPE_H 3 | #include 4 | 5 | 6 | #define GLMS_FOREACH_AST_TYPE(TOK) \ 7 | TOK(GLMS_AST_TYPE_EOF) \ 8 | TOK(GLMS_AST_TYPE_NOOP) \ 9 | TOK(GLMS_AST_TYPE_UNDEFINED) \ 10 | TOK(GLMS_AST_TYPE_VOID) \ 11 | TOK(GLMS_AST_TYPE_NULL) \ 12 | TOK(GLMS_AST_TYPE_ITERATOR) \ 13 | TOK(GLMS_AST_TYPE_COMPOUND) \ 14 | TOK(GLMS_AST_TYPE_ID) \ 15 | TOK(GLMS_AST_TYPE_STACK_PTR) \ 16 | TOK(GLMS_AST_TYPE_FUNC_OVERLOAD_PTR) \ 17 | TOK(GLMS_AST_TYPE_STRING) \ 18 | TOK(GLMS_AST_TYPE_RAW_GLSL) \ 19 | TOK(GLMS_AST_TYPE_CHAR) \ 20 | TOK(GLMS_AST_TYPE_NUMBER) \ 21 | TOK(GLMS_AST_TYPE_BOOL) \ 22 | TOK(GLMS_AST_TYPE_ARRAY) \ 23 | TOK(GLMS_AST_TYPE_VEC2) \ 24 | TOK(GLMS_AST_TYPE_VEC3) \ 25 | TOK(GLMS_AST_TYPE_VEC4) \ 26 | TOK(GLMS_AST_TYPE_MAT3) \ 27 | TOK(GLMS_AST_TYPE_MAT4) \ 28 | TOK(GLMS_AST_TYPE_TYPEDEF) \ 29 | TOK(GLMS_AST_TYPE_FDECL) \ 30 | TOK(GLMS_AST_TYPE_OBJECT) \ 31 | TOK(GLMS_AST_TYPE_STRUCT) \ 32 | TOK(GLMS_AST_TYPE_ENUM) \ 33 | TOK(GLMS_AST_TYPE_BINOP) \ 34 | TOK(GLMS_AST_TYPE_UNOP) \ 35 | TOK(GLMS_AST_TYPE_ACCESS) \ 36 | TOK(GLMS_AST_TYPE_BLOCK) \ 37 | TOK(GLMS_AST_TYPE_TERNARY) \ 38 | TOK(GLMS_AST_TYPE_LAYOUT) \ 39 | TOK(GLMS_AST_TYPE_IMPORT) \ 40 | TOK(GLMS_AST_TYPE_INCLUDE) \ 41 | TOK(GLMS_AST_TYPE_STACK) \ 42 | TOK(GLMS_AST_TYPE_FOR) \ 43 | TOK(GLMS_AST_TYPE_CALL) \ 44 | TOK(GLMS_AST_TYPE_FUNC) \ 45 | TOK(GLMS_AST_TYPE_RETURN) 46 | 47 | typedef enum { GLMS_FOREACH_AST_TYPE(GLMS_GENERATE_ENUM) } GLMSASTType; 48 | 49 | static const char * const GLMS_AST_TYPE_STR[] = { 50 | GLMS_FOREACH_AST_TYPE(GLMS_GENERATE_STRING)}; 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /include/glms/builtin.h: -------------------------------------------------------------------------------- 1 | #ifndef GLMS_BUILTIN_H 2 | #define GLMS_BUILTIN_H 3 | #include 4 | #include 5 | 6 | #include "glms/ast.h" 7 | 8 | void glms_builtin_init(GLMSEnv *env); 9 | 10 | int glms_fptr_dot(GLMSEval *eval, GLMSAST *ast, GLMSASTBuffer *args, 11 | GLMSStack *stack, GLMSAST *out); 12 | 13 | int glms_fptr_distance(GLMSEval *eval, GLMSAST *ast, GLMSASTBuffer *args, 14 | GLMSStack *stack, GLMSAST *out); 15 | 16 | int glms_fptr_cross(GLMSEval *eval, GLMSAST *ast, GLMSASTBuffer *args, 17 | GLMSStack *stack, GLMSAST *out); 18 | 19 | int glms_fptr_normalize(GLMSEval *eval, GLMSAST *ast, GLMSASTBuffer *args, 20 | GLMSStack *stack, GLMSAST *out); 21 | 22 | int glms_fptr_length(GLMSEval *eval, GLMSAST *ast, GLMSASTBuffer *args, 23 | GLMSStack *stack, GLMSAST *out); 24 | 25 | int glms_fptr_cos(GLMSEval *eval, GLMSAST *ast, GLMSASTBuffer *args, 26 | GLMSStack *stack, GLMSAST *out); 27 | 28 | int glms_fptr_sin(GLMSEval *eval, GLMSAST *ast, GLMSASTBuffer *args, 29 | GLMSStack *stack, GLMSAST *out); 30 | 31 | int glms_fptr_tan(GLMSEval *eval, GLMSAST *ast, GLMSASTBuffer *args, 32 | GLMSStack *stack, GLMSAST *out); 33 | 34 | int glms_fptr_atan(GLMSEval *eval, GLMSAST *ast, GLMSASTBuffer *args, 35 | GLMSStack *stack, GLMSAST *out); 36 | 37 | int glms_fptr_fract(GLMSEval *eval, GLMSAST *ast, GLMSASTBuffer *args, 38 | GLMSStack *stack, GLMSAST *out); 39 | 40 | int glms_fptr_abs(GLMSEval *eval, GLMSAST *ast, GLMSASTBuffer *args, 41 | GLMSStack *stack, GLMSAST *out); 42 | 43 | int glms_fptr_pow(GLMSEval *eval, GLMSAST *ast, GLMSASTBuffer *args, 44 | GLMSStack *stack, GLMSAST *out); 45 | 46 | int glms_fptr_log(GLMSEval *eval, GLMSAST *ast, GLMSASTBuffer *args, 47 | GLMSStack *stack, GLMSAST *out); 48 | 49 | int glms_fptr_log10(GLMSEval *eval, GLMSAST *ast, GLMSASTBuffer *args, 50 | GLMSStack *stack, GLMSAST *out); 51 | 52 | int glms_fptr_lerp(GLMSEval *eval, GLMSAST *ast, GLMSASTBuffer *args, 53 | GLMSStack *stack, GLMSAST *out); 54 | 55 | int glms_fptr_clamp(GLMSEval *eval, GLMSAST *ast, GLMSASTBuffer *args, 56 | GLMSStack *stack, GLMSAST *out); 57 | 58 | int glms_fptr_trace(GLMSEval *eval, GLMSAST *ast, GLMSASTBuffer *args, 59 | GLMSStack *stack, GLMSAST *out); 60 | 61 | int glms_fptr_random(GLMSEval *eval, GLMSAST *ast, GLMSASTBuffer *args, 62 | GLMSStack *stack, GLMSAST *out); 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /include/glms/constants.h: -------------------------------------------------------------------------------- 1 | #ifndef GLMS_CONSTANTS_H 2 | #define GLMS_CONSTANTS_H 3 | 4 | #define GLMS_MEMO_AST_PAGE_CAPACITY 30000 5 | #define GLMS_ARENA_AST_CAPACITY (GLMS_MEMO_AST_PAGE_CAPACITY * 2) 6 | #define GLMS_GC_SWEEP_THRESHOLD 64 7 | #define GLMS_GC_SWEEP_ITER (GLMS_GC_SWEEP_THRESHOLD / 2) 8 | 9 | #define GLMS_FUNC_OVERLOAD_TEMPLATE "__func_overload__%s" 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /include/glms/dl.h: -------------------------------------------------------------------------------- 1 | #ifndef GLMS_DL_H 2 | #define GLMS_DL_H 3 | #include 4 | 5 | void *glms_load_symbol(const char *filename, const char *funcname); 6 | GLMSExtensionEntryFunc glms_load_symbol_function(const char *filename, 7 | const char *funcname); 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /include/glms/emit/emit.h: -------------------------------------------------------------------------------- 1 | #ifndef GLMS_EMIT_H 2 | #define GLMS_EMIT_H 3 | #include 4 | #include 5 | #include 6 | 7 | typedef enum { GLMS_EMIT_MODE_UNDEFINED, GLMS_EMIT_MODE_GLSL } GLMSEmitMode; 8 | 9 | typedef struct { 10 | GLMSEmitMode mode; 11 | const char* out_path; 12 | } GLMSEmitConfig; 13 | 14 | typedef struct { 15 | GLMSEmitConfig config; 16 | GLMSStringBuilder builder; 17 | struct GLMS_ENV_STRUCT* env; 18 | bool initialized; 19 | } GLMSEmit; 20 | 21 | struct GLMS_ENV_STRUCT; 22 | 23 | int glms_emit_init(GLMSEmit *emit, struct GLMS_ENV_STRUCT* env, GLMSEmitConfig cfg); 24 | 25 | int glms_emit_destroy(GLMSEmit* emit); 26 | 27 | int glms_emit(GLMSEmit* emit, GLMSAST* ast); 28 | #endif 29 | -------------------------------------------------------------------------------- /include/glms/emit/glsl/emit_glsl.h: -------------------------------------------------------------------------------- 1 | #ifndef GLMS_EMIT_EMIT_GLSL_H 2 | #define GLMS_EMIT_EMIT_GLSL_H 3 | #include 4 | #include 5 | 6 | int glms_emit_glsl(GLMSEmit* emit, GLMSAST* ast); 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /include/glms/env.h: -------------------------------------------------------------------------------- 1 | #ifndef GLMS_ENV_H 2 | #define GLMS_ENV_H 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | 19 | 20 | #define GLMS_ENV_POSITION_INFO_STRING_CAP PATH_MAX 21 | 22 | typedef struct { 23 | bool debug; 24 | bool use_heap_strings; 25 | Memo* memo_ast; 26 | GLMSEmitConfig emit; 27 | } GLMSConfig; 28 | 29 | typedef struct GLMS_ENV_STRUCT { 30 | Memo memo_ast; 31 | Arena arena_ast; 32 | GLMSConfig config; 33 | bool initialized; 34 | const char *source; 35 | const char *entry_path; 36 | 37 | GLMSLexer lexer; 38 | GLMSParser parser; 39 | GLMSEval eval; 40 | GLMSStack stack; 41 | 42 | HashyMap globals; 43 | HashyMap types; 44 | 45 | GLMSAST *undefined; 46 | GLMSAST *stackptr; 47 | 48 | bool use_arena; 49 | 50 | GLMSAllocator string_alloc; 51 | 52 | char *last_joined_path; 53 | 54 | GLMSAST *root; 55 | 56 | GLMSEmit emit; 57 | 58 | bool has_builtins; 59 | 60 | char position_info[GLMS_ENV_POSITION_INFO_STRING_CAP]; 61 | } GLMSEnv; 62 | 63 | typedef void (*GLMSExtensionEntryFunc)(GLMSEnv *env); 64 | 65 | int glms_env_init(GLMSEnv *env, const char *source, const char *entry_path, 66 | GLMSConfig cfg); 67 | 68 | int glms_env_clear(GLMSEnv *env); 69 | 70 | GLMSAST* glms_env_parse(GLMSEnv* env, const char *source, 71 | GLMSConfig cfg); 72 | 73 | GLMSAST *glms_env_new_ast(GLMSEnv *env, GLMSASTType type, bool arena); 74 | 75 | GLMSAST *glms_env_new_ast_make(GLMSEnv *env, GLMSAST ast, bool arena); 76 | 77 | GLMSAST *glms_env_new_ast_number(GLMSEnv *env, float v, bool arena); 78 | 79 | GLMSAST *glms_env_new_ast_vec3(GLMSEnv *env, Vector3 v, bool arena); 80 | 81 | GLMSAST *glms_env_new_ast_string(GLMSEnv *env, const char *value, bool arena); 82 | 83 | GLMSAST *glms_env_new_ast_field(GLMSEnv *env, GLMSTokenType data_type, 84 | const char *name, bool arena); 85 | 86 | GLMSAST *glms_env_exec(GLMSEnv *env); 87 | 88 | GLMSAST *glms_env_exec_source(GLMSEnv *env, const char *source); 89 | 90 | int glms_env_reset(GLMSEnv *env); 91 | 92 | int glms_env_call_function(GLMSEnv *env, const char *name, GLMSASTBuffer args, 93 | GLMSAST *out); 94 | 95 | GLMSAST *glms_env_register_function(GLMSEnv *env, const char *name, 96 | GLMSFPTR fptr); 97 | 98 | int glms_env_register_function_signature(GLMSEnv *env, GLMSAST *ast, 99 | const char *name, 100 | GLMSFunctionSignature signature); 101 | 102 | GLMSAST *glms_env_register_struct(GLMSEnv *env, const char *name, 103 | GLMSAST **fields, int fields_length); 104 | 105 | GLMSAST *glms_env_register_any(GLMSEnv *env, const char *name, GLMSAST *ast); 106 | 107 | GLMSAST *glms_env_register_type(GLMSEnv *env, const char *name, GLMSAST *ast, 108 | GLMSASTContructor constructor, 109 | GLMSASTSwizzle swizzle, 110 | GLMSASTToString to_string, 111 | GLMSASTDestructor destructor); 112 | 113 | GLMSAST *glms_env_lookup_function(GLMSEnv *env, const char *name); 114 | 115 | GLMSAST *glms_env_lookup(GLMSEnv *env, const char *name); 116 | 117 | GLMSAST *glms_env_lookup_type(GLMSEnv *env, const char *name); 118 | 119 | GLMSAST *glms_env_get_type_for(GLMSEnv *env, GLMSAST *ast); 120 | 121 | GLMSAST *glms_env_apply_type(GLMSEnv *env, GLMSEval *eval, GLMSStack *stack, 122 | GLMSAST *ast); 123 | 124 | const char *glms_env_get_path_for(GLMSEnv *env, const char *path); 125 | 126 | int glms_env_export_docstrings(GLMSEnv *env, const char *filepath); 127 | 128 | int glms_env_emit(GLMSEnv *env); 129 | 130 | const char* glms_env_get_emit(GLMSEnv* env); 131 | 132 | const char *glms_env_get_position_info(GLMSEnv *env); 133 | 134 | const char* glms_env_get_current_filename(GLMSEnv* env); 135 | #endif 136 | -------------------------------------------------------------------------------- /include/glms/eval.h: -------------------------------------------------------------------------------- 1 | #ifndef GLMS_EVAL_H 2 | #define GLMS_EVAL_H 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | struct GLMS_ENV_STRUCT; 9 | 10 | #define GLMS_EVAL_VISITED_PATHS_MAP_CAPACITY 64 11 | 12 | typedef struct GLMS_EVAL_STRUCT { 13 | struct GLMS_ENV_STRUCT *env; 14 | HashyMap visited_paths; 15 | bool initialized; 16 | } GLMSEval; 17 | 18 | int glms_eval_init(GLMSEval *eval, struct GLMS_ENV_STRUCT *env); 19 | 20 | int glms_eval_clear(GLMSEval* eval); 21 | 22 | GLMSAST glms_eval(GLMSEval *eval, GLMSAST ast, GLMSStack *stack); 23 | 24 | GLMSAST *glms_eval_lookup(GLMSEval *eval, GLMSStack *stack, const char *key); 25 | 26 | bool glms_eval_expect(GLMSEval *eval, GLMSStack *stack, GLMSASTType *types, 27 | int nr_types, GLMSASTBuffer *args); 28 | 29 | GLMSAST glms_eval_call_func(GLMSEval *eval, GLMSStack *stack, GLMSAST *func, 30 | GLMSASTBuffer args); 31 | 32 | GLMSAST glms_eval_assign(GLMSEval *eval, GLMSAST left, GLMSAST right, 33 | GLMSStack *stack); 34 | 35 | void glms_eval_push_args(GLMSEval *eval, GLMSStack *stack, GLMSAST *func, 36 | GLMSASTBuffer args); 37 | 38 | GLMSAST glms_eval_import(GLMSEval *eval, GLMSAST ast, GLMSStack *stack); 39 | 40 | GLMSAST glms_eval_include(GLMSEval *eval, GLMSAST ast, GLMSStack *stack); 41 | #endif 42 | -------------------------------------------------------------------------------- /include/glms/fptr.h: -------------------------------------------------------------------------------- 1 | #ifndef GLMS_FPTR_H 2 | #define GLMS_FPTR_H 3 | 4 | struct GLMS_STACK_STRUCT; 5 | struct GLMS_AST_STRUCT; 6 | struct GLMS_EVAL_STRUCT; 7 | struct GLMS_GLMSAST_LIST_STRUCT; 8 | struct GLMS_BUFFER_GLMSAST; 9 | 10 | typedef int (*GLMSFPTR)(struct GLMS_EVAL_STRUCT* eval, 11 | struct GLMS_AST_STRUCT* ast, 12 | struct GLMS_BUFFER_GLMSAST* args, 13 | struct GLMS_STACK_STRUCT* stack, 14 | struct GLMS_AST_STRUCT* out); 15 | #endif 16 | -------------------------------------------------------------------------------- /include/glms/glms.h: -------------------------------------------------------------------------------- 1 | #ifndef GLMS_H 2 | #define GLMS_H 3 | #include 4 | #endif 5 | -------------------------------------------------------------------------------- /include/glms/io.h: -------------------------------------------------------------------------------- 1 | #ifndef GLMS_IO_H 2 | #define GLMS_IO_H 3 | #include 4 | bool glms_file_exists(const char *path); 5 | char *glms_get_file_contents(const char *filepath); 6 | #endif 7 | -------------------------------------------------------------------------------- /include/glms/iterator.h: -------------------------------------------------------------------------------- 1 | #ifndef GLMS_ITERATOR_H 2 | #define GLMS_ITERATOR_H 3 | 4 | struct GLMS_AST_STRUCT; 5 | struct GLMS_ENV_STRUCT; 6 | 7 | typedef struct { 8 | int index; 9 | struct GLMS_AST_STRUCT* ast; 10 | } GLMSIterator; 11 | 12 | typedef int (*GLMSIteratorNext)(struct GLMS_ENV_STRUCT* env, 13 | struct GLMS_AST_STRUCT* self, GLMSIterator* it, 14 | struct GLMS_AST_STRUCT* out); 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /include/glms/lexer.h: -------------------------------------------------------------------------------- 1 | #ifndef GLMS_LEXER_H 2 | #define GLMS_LEXER_H 3 | #include 4 | #include 5 | #include 6 | 7 | #define GLMS_LEXER_LINE_COLUMN_TEXT_CAP 256 8 | 9 | typedef struct { 10 | int64_t i; 11 | int64_t length; 12 | 13 | int64_t line; 14 | int64_t column; 15 | 16 | char c; 17 | const char* source; 18 | bool initialized; 19 | 20 | char linecol[GLMS_LEXER_LINE_COLUMN_TEXT_CAP]; 21 | } GLMSLexer; 22 | 23 | int glms_lexer_init(GLMSLexer* lexer, const char* source); 24 | 25 | int glms_lexer_next(GLMSLexer *lexer, GLMSToken *out); 26 | 27 | int glms_lexer_reset(GLMSLexer *lexer); 28 | 29 | const char* glms_lexer_get_position_text(GLMSLexer* lexer); 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /include/glms/list.h: -------------------------------------------------------------------------------- 1 | #ifndef GLMS_TYPE_LIST_H 2 | #define GLMS_TYPE_LIST_H 3 | #include 4 | #include 5 | #include 6 | 7 | #define GLMS_DEFINE_LIST(T) \ 8 | typedef struct GLMS_##T##_LIST_STRUCT { \ 9 | T **items; \ 10 | int64_t length; \ 11 | bool initialized; \ 12 | } T##List; \ 13 | int glms_##T##_list_init(T##List *list); \ 14 | int glms_##T##_list_make_unique(T##List *list); \ 15 | T *glms_##T##_list_push(T##List *list, T *item); \ 16 | T *glms_##T##_list_push_unique(T##List *list, T *item); \ 17 | T *glms_##T##_list_popi(T##List *list, int64_t index); \ 18 | int glms_##T##_list_clear(T##List *list); \ 19 | T *glms_##T##_list_remove(T##List *list, T *item); \ 20 | bool glms_##T##_list_includes(T##List list, T *item); \ 21 | int64_t glms_##T##_list_count(T##List list, T *item); \ 22 | int glms_##T##_list_concat(T##List *a, T##List b); \ 23 | bool glms_##T##_list_is_empty(T##List list); 24 | 25 | #define GLMS_IMPLEMENT_LIST(T) \ 26 | int glms_##T##_list_init(T##List *list) { \ 27 | if (!list) return 0; \ 28 | if (list->initialized) return 1; \ 29 | list->initialized = true; \ 30 | list->items = 0; \ 31 | list->length = 0; \ 32 | return 1; \ 33 | } \ 34 | int glms_##T##_list_make_unique(T##List *list) { \ 35 | if (glms_##T##_list_is_empty(*list)) return 1; \ 36 | for (int64_t i = 0; i < list->length; i++) { \ 37 | if (glms_##T##_list_count(*list, list->items[i]) > 1) { \ 38 | glms_##T##_list_remove(list, list->items[i]); \ 39 | } \ 40 | } \ 41 | return 1; \ 42 | } \ 43 | int64_t glms_##T##_list_count(T##List list, T *item) { \ 44 | if (glms_##T##_list_is_empty(list)) return 0; \ 45 | int64_t count = 0; \ 46 | for (int64_t i = 0; i < list.length; i++) { \ 47 | if (list.items[i] == item) count++; \ 48 | } \ 49 | return count; \ 50 | } \ 51 | bool glms_##T##_list_includes(T##List list, T *item) { \ 52 | if (glms_##T##_list_is_empty(list)) return false; \ 53 | for (int64_t i = 0; i < list.length; i++) { \ 54 | if (list.items[i] == item) return true; \ 55 | } \ 56 | return false; \ 57 | } \ 58 | T *glms_##T##_list_remove(T##List *list, T *item) { \ 59 | if (!list) return item; \ 60 | if (!list->initialized) \ 61 | GLMS_WARNING_RETURN(item, stderr, "List not initialized\n"); \ 62 | \ 63 | if (glms_##T##_list_is_empty(*list)) return item; \ 64 | \ 65 | if (list->length - 1 <= 0) { \ 66 | glms_##T##_list_clear(list); \ 67 | return item; \ 68 | } \ 69 | \ 70 | int64_t index = -1; \ 71 | for (int64_t i = 0; i < list->length; i++) { \ 72 | if (list->items[i] == item) { \ 73 | index = i; \ 74 | break; \ 75 | } \ 76 | } \ 77 | if (index <= -1) return item; \ 78 | \ 79 | for (int i = index; i < list->length - 1; i++) { \ 80 | list->items[i] = list->items[i + 1]; \ 81 | } \ 82 | \ 83 | list->items = (T **)realloc(list->items, (list->length - 1) * sizeof(T)); \ 84 | list->length -= 1; \ 85 | list->length = MAX(0, list->length); \ 86 | \ 87 | return item; \ 88 | } \ 89 | T *glms_##T##_list_popi(T##List *list, int64_t index) { \ 90 | if (!list) return 0; \ 91 | if (!list->initialized) \ 92 | GLMS_WARNING_RETURN(0, stderr, "List not initialized\n"); \ 93 | \ 94 | if (list->items == 0 || list->length <= 0 || index < 0 || \ 95 | index >= list->length) \ 96 | return 0; \ 97 | \ 98 | T *out = list->items[index]; \ 99 | \ 100 | if (list->length - 1 <= 0) { \ 101 | glms_##T##_list_clear(list); \ 102 | return out; \ 103 | } \ 104 | \ 105 | for (int i = index; i < MAX(0, list->length - 1); i++) { \ 106 | list->items[i] = list->items[i + 1]; \ 107 | } \ 108 | \ 109 | list->items = (T **)realloc(list->items, (list->length - 1) * sizeof(T)); \ 110 | list->length -= 1; \ 111 | list->length = MAX(0, list->length); \ 112 | \ 113 | return out; \ 114 | } \ 115 | T *glms_##T##_list_push_unique(T##List *list, T *item) { \ 116 | if (glms_##T##_list_includes(*list, item)) return item; \ 117 | return glms_##T##_list_push(list, item); \ 118 | } \ 119 | T *glms_##T##_list_push(T##List *list, T *item) { \ 120 | if (!list) return 0; \ 121 | if (!list->initialized) \ 122 | GLMS_WARNING_RETURN(0, stderr, "List not initialized\n"); \ 123 | if (!item) return 0; \ 124 | list->items = \ 125 | (T **)realloc(list->items, (list->length + 1) * sizeof(T *)); \ 126 | if (!list->items) \ 127 | GLMS_WARNING_RETURN(0, stderr, "Could not realloc list.\n"); \ 128 | list->items[list->length++] = item; \ 129 | return item; \ 130 | } \ 131 | int glms_##T##_list_concat(T##List *a, T##List b) { \ 132 | if (!a) return 0; \ 133 | if (b.length <= 0 || b.items == 0) return 0; \ 134 | for (int64_t i = 0; i < b.length; i++) { \ 135 | if (!glms_##T##_list_includes(*a, b.items[i])) { \ 136 | glms_##T##_list_push(a, b.items[i]); \ 137 | } \ 138 | } \ 139 | return 1; \ 140 | } \ 141 | int glms_##T##_list_clear(T##List *list) { \ 142 | if (!list) return 0; \ 143 | if (list->items != 0) { \ 144 | free(list->items); \ 145 | list->items = 0; \ 146 | } \ 147 | list->length = 0; \ 148 | return 1; \ 149 | } \ 150 | bool glms_##T##_list_is_empty(T##List list) { \ 151 | return (list.items == 0 || list.length <= 0); \ 152 | } 153 | 154 | #endif 155 | -------------------------------------------------------------------------------- /include/glms/macros.h: -------------------------------------------------------------------------------- 1 | #ifndef GLMS_MACROS_H 2 | #define GLMS_MACROS_H 3 | #include 4 | #include 5 | 6 | #ifndef NEW 7 | #define NEW(T) ((T *)(calloc(1, sizeof(T)))) 8 | #endif 9 | 10 | #ifndef OR 11 | #define OR(a, b) (a ? a : b) 12 | #endif 13 | 14 | #ifndef MIN 15 | #define MIN(a, b) (a < b ? a : b) 16 | #endif 17 | 18 | #ifndef MAX 19 | #define MAX(a, b) (a > b ? a : b) 20 | #endif 21 | 22 | #ifndef ABS 23 | #define ABS(a) (a < 0 ? (a * -1) : a) 24 | #endif 25 | 26 | #define GLMS_CLI_RED "\x1B[31m" 27 | #define GLMS_CLI_GREEN "\x1B[32m" 28 | #define GLMS_CLI_YELLLOW "\x1B[33m" 29 | #define GLMS_CLI_BLUE "\x1B[34m" 30 | #define GLMS_CLI_MAGENTA "\x1B[35m" 31 | #define GLMS_CLI_CYAN "\x1B[36m" 32 | #define GLMS_CLI_WHITE "\x1B[37m" 33 | #define GLMS_CLI_RESET "\x1B[0m" 34 | 35 | #define GLMS_WARNING(...) \ 36 | { \ 37 | printf(GLMS_CLI_RED "(GLMS)(Warning)(%s): \n" GLMS_CLI_RESET, __func__); \ 38 | fprintf(__VA_ARGS__); \ 39 | } 40 | #define GLMS_WARNING_RETURN(ret, ...) \ 41 | { \ 42 | printf("\n****\n"); \ 43 | printf(GLMS_CLI_RED "(GLMS)(Warning)(%s): \n" GLMS_CLI_RESET, __func__); \ 44 | fprintf(__VA_ARGS__); \ 45 | printf("\n****\n"); \ 46 | return ret; \ 47 | } 48 | 49 | #define GLMS_GENERATE_ENUM(ENUM) ENUM, 50 | #define GLMS_GENERATE_STRING(STRING) #STRING, 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /include/glms/math.h: -------------------------------------------------------------------------------- 1 | #ifndef GLMS_MATH_H 2 | #define GLMS_MATH_H 3 | #include 4 | #include 5 | #include 6 | 7 | float glms_smoothstep_factor(float edge0, float edge1, float x); 8 | Vector3 glms_smoothstep_vec3_factor(Vector3 edge0, Vector3 edge1, float x); 9 | Vector3 glms_smoothstep_vec3_vec3(Vector3 edge0, Vector3 edge1, Vector3 x); 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /include/glms/modules/array.h: -------------------------------------------------------------------------------- 1 | #ifndef GLMS_MODULES_ARRAY_H 2 | #define GLMS_MODULES_ARRAY_H 3 | #include 4 | void glms_array_type(GLMSEnv *env); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /include/glms/modules/fetch.h: -------------------------------------------------------------------------------- 1 | #ifndef GLMS_MODULES_FETCH_H 2 | #define GLMS_MODULES_FETCH_H 3 | 4 | #include 5 | 6 | void glms_fetch(GLMSEnv* env); 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /include/glms/modules/file.h: -------------------------------------------------------------------------------- 1 | #ifndef GLMS_MODULES_FILE_H 2 | #define GLMS_MODULES_FILE_H 3 | #include 4 | #include 5 | typedef struct { 6 | FILE *fp; 7 | bool open; 8 | } GLMSFile; 9 | 10 | typedef struct { 11 | GLMSFile *file; 12 | char *last_ptr; 13 | char *line; 14 | 15 | int64_t read_bytes; 16 | int64_t pos; 17 | 18 | } GLMSFileIteratorState; 19 | 20 | void glms_file_type(GLMSEnv *env); 21 | 22 | void glms_file_constructor(GLMSEval *eval, GLMSStack *stack, 23 | GLMSASTBuffer *args, GLMSAST *self); 24 | #endif 25 | -------------------------------------------------------------------------------- /include/glms/modules/image.h: -------------------------------------------------------------------------------- 1 | #ifndef GLMS_MODULES_IMAGE_H 2 | #define GLMS_MODULES_IMAGE_H 3 | #include 4 | 5 | void glms_struct_image_constructor(GLMSEval *eval, GLMSStack *stack, 6 | GLMSASTBuffer *args, GLMSAST *self); 7 | void glms_struct_image(GLMSEnv *env); 8 | #endif 9 | -------------------------------------------------------------------------------- /include/glms/modules/iterator.h: -------------------------------------------------------------------------------- 1 | #ifndef GLMS_MODULES_ITERATOR_H 2 | #define GLMS_MODULES_ITERATOR_H 3 | #include 4 | void glms_iterator_type(GLMSEnv *env); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /include/glms/modules/json.h: -------------------------------------------------------------------------------- 1 | #ifndef GLMS_MODULES_JSON_H 2 | #define GLMS_MODULES_JSON_H 3 | 4 | #include 5 | 6 | void glms_json(GLMSEnv* env); 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /include/glms/modules/mat3.h: -------------------------------------------------------------------------------- 1 | #ifndef GLMS_MODULES_MAT3_H 2 | #define GLMS_MODULES_MAT3_H 3 | #include 4 | void glms_mat3_type(GLMSEnv *env); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /include/glms/modules/mat4.h: -------------------------------------------------------------------------------- 1 | #ifndef GLMS_MODULES_MAT4_H 2 | #define GLMS_MODULES_MAT4_H 3 | #include 4 | void glms_mat4_type(GLMSEnv *env); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /include/glms/modules/string.h: -------------------------------------------------------------------------------- 1 | #ifndef GLMS_MODULES_STRING_H 2 | #define GLMS_MODULES_STRING_H 3 | #include 4 | void glms_string_type(GLMSEnv *env); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /include/glms/modules/vec2.h: -------------------------------------------------------------------------------- 1 | #ifndef GLMS_MODULES_VEC2_H 2 | #define GLMS_MODULES_VEC2_H 3 | #include 4 | void glms_struct_vec2(GLMSEnv *env); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /include/glms/modules/vec3.h: -------------------------------------------------------------------------------- 1 | #ifndef GLMS_MODULES_VEC3_H 2 | #define GLMS_MODULES_VEC3_H 3 | #include 4 | void glms_struct_vec3(GLMSEnv *env); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /include/glms/modules/vec4.h: -------------------------------------------------------------------------------- 1 | #ifndef GLMS_MODULES_VEC4_H 2 | #define GLMS_MODULES_VEC4_H 3 | #include 4 | 5 | void glms_struct_vec4(GLMSEnv *env); 6 | #endif 7 | -------------------------------------------------------------------------------- /include/glms/parser.h: -------------------------------------------------------------------------------- 1 | #ifndef GLMS_PARSER_H 2 | #define GLMS_PARSER_H 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | struct GLMS_ENV_STRUCT; 9 | 10 | typedef struct { 11 | struct GLMS_ENV_STRUCT* env; 12 | bool error; 13 | bool finished; 14 | GLMSToken token; 15 | bool initialized; 16 | 17 | HashyMap symbols; 18 | } GLMSParser; 19 | 20 | int glms_parser_init(GLMSParser* parser, struct GLMS_ENV_STRUCT* env); 21 | 22 | int glms_parser_eat(GLMSParser* parser, GLMSTokenType token_type); 23 | 24 | GLMSAST* glms_parser_parse(GLMSParser* parser); 25 | 26 | GLMSAST* glms_parser_parse_id(GLMSParser* parser, bool skip_next); 27 | 28 | GLMSAST* glms_parser_parse_number(GLMSParser* parser); 29 | GLMSAST* glms_parser_parse_int(GLMSParser* parser); 30 | GLMSAST* glms_parser_parse_uint64(GLMSParser* parser); 31 | GLMSAST* glms_parser_parse_float(GLMSParser* parser); 32 | GLMSAST* glms_parser_parse_null(GLMSParser* parser); 33 | GLMSAST* glms_parser_parse_bool(GLMSParser* parser); 34 | GLMSAST* glms_parser_parse_string(GLMSParser* parser); 35 | GLMSAST* glms_parser_parse_glsl_string(GLMSParser* parser); 36 | GLMSAST* glms_parser_parse_template_string(GLMSParser* parser); 37 | GLMSAST* glms_parser_parse_array(GLMSParser* parser); 38 | GLMSAST* glms_parser_parse_object(GLMSParser* parser); 39 | 40 | GLMSAST* glms_parser_parse_expr(GLMSParser* parser); 41 | 42 | GLMSAST* glms_parser_parse_compound(GLMSParser* parser, bool skip_brace); 43 | 44 | GLMSAST* glms_parser_parse_term(GLMSParser* parser); 45 | GLMSAST* glms_parser_parse_factor(GLMSParser* parser); 46 | GLMSAST* glms_parser_parse_call(GLMSParser* parser, GLMSAST* left); 47 | GLMSAST* glms_parser_parse_arrow_function(GLMSParser* parser); 48 | GLMSAST* glms_parser_parse_function(GLMSParser* parser); 49 | GLMSAST* glms_parser_parse_block(GLMSParser* parser); 50 | GLMSAST* glms_parser_parse_ternary(GLMSParser* parser, GLMSAST* condition); 51 | GLMSAST* glms_parser_parse_for(GLMSParser* parser); 52 | 53 | GLMSAST* glms_parser_parse_binop(GLMSParser* parser, GLMSAST* left); 54 | GLMSAST* glms_parser_parse_struct(GLMSParser* parser); 55 | GLMSAST* glms_parser_parse_enum(GLMSParser* parser); 56 | GLMSAST* glms_parser_parse_unop(GLMSParser* parser); 57 | GLMSAST* glms_parser_parse_typedef(GLMSParser* parser); 58 | GLMSAST* glms_parser_parse_import(GLMSParser* parser); 59 | GLMSAST* glms_parser_parse_include(GLMSParser* parser); 60 | GLMSAST* glms_parser_parse_fdecl(GLMSParser* parser); 61 | GLMSAST* glms_parser_parse_layout(GLMSParser* parser); 62 | 63 | GLMSAST* glms_parser_lookup(GLMSParser* parser, const char* key); 64 | 65 | bool glms_parser_peek_check_arrow_function(GLMSParser* parser); 66 | bool glms_parser_peek_check_glsl_function(GLMSParser* parser); 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /include/glms/stack.h: -------------------------------------------------------------------------------- 1 | #ifndef GLMS_STACK_H 2 | #define GLMS_STACK_H 3 | #include 4 | #include 5 | #include 6 | 7 | struct GLMS_ENV_STRUCT; 8 | 9 | #define GLMS_STACK_CAPACITY 256 10 | 11 | typedef struct GLMS_STACK_STRUCT { 12 | HashyMap locals; 13 | bool initialized; 14 | //const char* names[GLMS_STACK_CAPACITY]; 15 | //int names_length; 16 | int depth; 17 | 18 | bool return_flag; 19 | 20 | } GLMSStack; 21 | 22 | int glms_stack_init(GLMSStack* stack); 23 | 24 | GLMSAST* glms_stack_push(GLMSStack* stack, const char* name, GLMSAST* ast); 25 | GLMSAST* glms_stack_pop(GLMSStack* stack, const char* name); 26 | GLMSAST* glms_stack_get(GLMSStack* stack, const char* name); 27 | 28 | int glms_stack_save(GLMSStack* stack); 29 | int glms_stack_restore(GLMSStack* stack); 30 | 31 | void glms_stack_dump(GLMSStack* stack, struct GLMS_ENV_STRUCT* env); 32 | 33 | int glms_stack_copy(GLMSStack src, GLMSStack* dest); 34 | 35 | int glms_stack_clear(GLMSStack* stack); 36 | 37 | int glms_stack_clear_trash(GLMSStack* stack); 38 | #endif 39 | -------------------------------------------------------------------------------- /include/glms/string_builder.h: -------------------------------------------------------------------------------- 1 | #ifndef GLMS_STRING_BUILDER_H 2 | #define GLMS_STRING_BUILDER_H 3 | #include 4 | typedef struct { 5 | char* buffer; 6 | int64_t length; 7 | int64_t capacity; 8 | } GLMSStringBuilder; 9 | 10 | int glms_string_builder_append(GLMSStringBuilder *builder, const char *value); 11 | 12 | int glms_string_builder_append_indented(GLMSStringBuilder *builder, const char *value, int indent, const char* indent_v); 13 | 14 | int glms_string_builder_destroy(GLMSStringBuilder* builder); 15 | #endif 16 | -------------------------------------------------------------------------------- /include/glms/string_view.h: -------------------------------------------------------------------------------- 1 | #ifndef GLMS_STRING_VIEW_H 2 | #define GLMS_STRING_VIEW_H 3 | #include 4 | 5 | #define GLMS_STRING_VIEW_CAPACITY 1024 6 | 7 | typedef struct { 8 | int64_t length; 9 | const char* ptr; 10 | char tmp_buffer[GLMS_STRING_VIEW_CAPACITY]; 11 | } GLMSStringView; 12 | 13 | const char* glms_string_view_get_value(GLMSStringView* view); 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /include/glms/token.h: -------------------------------------------------------------------------------- 1 | #ifndef GLMS_TOKEN_H 2 | #define GLMS_TOKEN_H 3 | #include 4 | #include 5 | #include 6 | 7 | #define GLMS_FOREACH_TOKEN_TYPE(TOK) \ 8 | TOK(GLMS_TOKEN_TYPE_NONE) \ 9 | TOK(GLMS_TOKEN_TYPE_EOF) \ 10 | TOK(GLMS_TOKEN_TYPE_LBRACE) \ 11 | TOK(GLMS_TOKEN_TYPE_RBRACE) \ 12 | TOK(GLMS_TOKEN_TYPE_LBRACKET) \ 13 | TOK(GLMS_TOKEN_TYPE_RBRACKET) \ 14 | TOK(GLMS_TOKEN_TYPE_LPAREN) \ 15 | TOK(GLMS_TOKEN_TYPE_RPAREN) \ 16 | TOK(GLMS_TOKEN_TYPE_SEMI) \ 17 | TOK(GLMS_TOKEN_TYPE_COMMA) \ 18 | TOK(GLMS_TOKEN_TYPE_COLON) \ 19 | TOK(GLMS_TOKEN_TYPE_DOT) \ 20 | TOK(GLMS_TOKEN_TYPE_ID) \ 21 | TOK(GLMS_TOKEN_TYPE_STRING) \ 22 | TOK(GLMS_TOKEN_TYPE_TEMPLATE_STRING) \ 23 | TOK(GLMS_TOKEN_TYPE_NUMBER) \ 24 | TOK(GLMS_TOKEN_TYPE_INT) \ 25 | TOK(GLMS_TOKEN_TYPE_UINT64) \ 26 | TOK(GLMS_TOKEN_TYPE_FLOAT) \ 27 | TOK(GLMS_TOKEN_TYPE_ADD) \ 28 | TOK(GLMS_TOKEN_TYPE_ADD_ADD) \ 29 | TOK(GLMS_TOKEN_TYPE_ADD_EQUALS) \ 30 | TOK(GLMS_TOKEN_TYPE_AND_AND) \ 31 | TOK(GLMS_TOKEN_TYPE_PIPE_PIPE) \ 32 | TOK(GLMS_TOKEN_TYPE_QUESTION) \ 33 | TOK(GLMS_TOKEN_TYPE_MUL) \ 34 | TOK(GLMS_TOKEN_TYPE_MUL_EQUALS) \ 35 | TOK(GLMS_TOKEN_TYPE_SUB) \ 36 | TOK(GLMS_TOKEN_TYPE_SUB_SUB) \ 37 | TOK(GLMS_TOKEN_TYPE_SUB_EQUALS) \ 38 | TOK(GLMS_TOKEN_TYPE_DIV) \ 39 | TOK(GLMS_TOKEN_TYPE_DIV_EQUALS) \ 40 | TOK(GLMS_TOKEN_TYPE_PERCENT) \ 41 | TOK(GLMS_TOKEN_TYPE_EQUALS) \ 42 | TOK(GLMS_TOKEN_TYPE_EQUALS_EQUALS) \ 43 | TOK(GLMS_TOKEN_TYPE_GT) \ 44 | TOK(GLMS_TOKEN_TYPE_LT) \ 45 | TOK(GLMS_TOKEN_TYPE_GTE) \ 46 | TOK(GLMS_TOKEN_TYPE_LTE) \ 47 | TOK(GLMS_TOKEN_TYPE_EXCLAM) \ 48 | TOK(GLMS_TOKEN_TYPE_SPECIAL_NULL) \ 49 | TOK(GLMS_TOKEN_TYPE_SPECIAL_IMPORT) \ 50 | TOK(GLMS_TOKEN_TYPE_SPECIAL_INCLUDE) \ 51 | TOK(GLMS_TOKEN_TYPE_SPECIAL_LAYOUT) \ 52 | TOK(GLMS_TOKEN_TYPE_SPECIAL_GLSL) \ 53 | TOK(GLMS_TOKEN_TYPE_SPECIAL_AS) \ 54 | TOK(GLMS_TOKEN_TYPE_SPECIAL_IN) \ 55 | TOK(GLMS_TOKEN_TYPE_SPECIAL_INOUT) \ 56 | TOK(GLMS_TOKEN_TYPE_SPECIAL_OUT) \ 57 | TOK(GLMS_TOKEN_TYPE_SPECIAL_TYPEDEF) \ 58 | TOK(GLMS_TOKEN_TYPE_SPECIAL_FDECL) \ 59 | TOK(GLMS_TOKEN_TYPE_SPECIAL_USER_TYPE) \ 60 | TOK(GLMS_TOKEN_TYPE_SPECIAL_CONST) \ 61 | TOK(GLMS_TOKEN_TYPE_SPECIAL_LET) \ 62 | TOK(GLMS_TOKEN_TYPE_SPECIAL_STRUCT) \ 63 | TOK(GLMS_TOKEN_TYPE_SPECIAL_VEC2) \ 64 | TOK(GLMS_TOKEN_TYPE_SPECIAL_VEC3) \ 65 | TOK(GLMS_TOKEN_TYPE_SPECIAL_VEC4) \ 66 | TOK(GLMS_TOKEN_TYPE_SPECIAL_MAT3) \ 67 | TOK(GLMS_TOKEN_TYPE_SPECIAL_MAT4) \ 68 | TOK(GLMS_TOKEN_TYPE_SPECIAL_UNIFORM) \ 69 | TOK(GLMS_TOKEN_TYPE_SPECIAL_READONLY) \ 70 | TOK(GLMS_TOKEN_TYPE_SPECIAL_BUFFER) \ 71 | TOK(GLMS_TOKEN_TYPE_SPECIAL_SAMPLER_2D) \ 72 | TOK(GLMS_TOKEN_TYPE_SPECIAL_SAMPLER_3D) \ 73 | TOK(GLMS_TOKEN_TYPE_SPECIAL_SAMPLER_CUBE) \ 74 | TOK(GLMS_TOKEN_TYPE_SPECIAL_ENUM) \ 75 | TOK(GLMS_TOKEN_TYPE_SPECIAL_STRING) \ 76 | TOK(GLMS_TOKEN_TYPE_SPECIAL_NUMBER) \ 77 | TOK(GLMS_TOKEN_TYPE_SPECIAL_INT) \ 78 | TOK(GLMS_TOKEN_TYPE_SPECIAL_UINT64) \ 79 | TOK(GLMS_TOKEN_TYPE_SPECIAL_FLOAT) \ 80 | TOK(GLMS_TOKEN_TYPE_SPECIAL_VOID) \ 81 | TOK(GLMS_TOKEN_TYPE_SPECIAL_ARRAY) \ 82 | TOK(GLMS_TOKEN_TYPE_SPECIAL_OBJECT) \ 83 | TOK(GLMS_TOKEN_TYPE_SPECIAL_FOR) \ 84 | TOK(GLMS_TOKEN_TYPE_SPECIAL_SWITCH) \ 85 | TOK(GLMS_TOKEN_TYPE_SPECIAL_CASE) \ 86 | TOK(GLMS_TOKEN_TYPE_SPECIAL_BREAK) \ 87 | TOK(GLMS_TOKEN_TYPE_SPECIAL_WHILE) \ 88 | TOK(GLMS_TOKEN_TYPE_SPECIAL_FALSE) \ 89 | TOK(GLMS_TOKEN_TYPE_SPECIAL_TRUE) \ 90 | TOK(GLMS_TOKEN_TYPE_SPECIAL_BOOL) \ 91 | TOK(GLMS_TOKEN_TYPE_SPECIAL_IF) \ 92 | TOK(GLMS_TOKEN_TYPE_SPECIAL_ELSE) \ 93 | TOK(GLMS_TOKEN_TYPE_SPECIAL_FUNCTION) \ 94 | TOK(GLMS_TOKEN_TYPE_SPECIAL_RETURN) 95 | 96 | typedef enum { GLMS_FOREACH_TOKEN_TYPE(GLMS_GENERATE_ENUM) } GLMSTokenType; 97 | 98 | static const char * const GLMS_TOKEN_TYPE_STR[] = { 99 | GLMS_FOREACH_TOKEN_TYPE(GLMS_GENERATE_STRING)}; 100 | 101 | typedef struct { 102 | GLMSTokenType type; 103 | GLMSStringView value; 104 | char c; 105 | } GLMSToken; 106 | 107 | bool glms_token_type_is_flag(GLMSTokenType type); 108 | #endif 109 | -------------------------------------------------------------------------------- /include/glms/type.h: -------------------------------------------------------------------------------- 1 | #ifndef GLMS_TYPE_H 2 | #define GLMS_TYPE_H 3 | #include 4 | #include 5 | 6 | typedef struct { 7 | GLMSASTType ast_type; 8 | char* typename; 9 | char* valuename; 10 | } GLMSType; 11 | 12 | typedef struct { 13 | GLMSType return_type; 14 | GLMSType* args; 15 | int args_length; 16 | char* description; 17 | } GLMSFunctionSignature; 18 | 19 | GLMS_DEFINE_BUFFER(GLMSFunctionSignature); 20 | 21 | #define GLMS_SIGNATURE_NONE \ 22 | (GLMSFunctionSignature) { 0 } 23 | 24 | GLMSFunctionSignature glms_make_signature(GLMSType ret_type, GLMSType* args, 25 | int args_length); 26 | 27 | char* glms_function_signature_to_string(GLMSFunctionSignature signa, 28 | const char* func_name); 29 | 30 | int glms_type_destroy(GLMSType* type); 31 | int glms_signature_destroy(GLMSFunctionSignature* signa); 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /include/glms/version.h: -------------------------------------------------------------------------------- 1 | #ifndef GLMS_VERSION_H 2 | #define GLMS_VERSION_H 3 | 4 | #define GLMS_VERSION_MAJOR 0 5 | #define GLMS_VERSION_MINOR 0 6 | #define GLMS_VERSION_PATCH 5 7 | 8 | #define GLMS_VERSION_STRING "0.0.5" 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /profile.sh: -------------------------------------------------------------------------------- 1 | cmake -DCMAKE_CXX_FLAGS=-pg -DCMAKE_EXE_LINKER_FLAGS=-pg -DCMAKE_SHARED_LINKER_FLAGS=-pg -DDO_PROFILE=1 ../ 2 | make -j8 && $1 3 | gprof $1 gmon.out > analysis.txt 4 | gprof2dot analysis.txt | dot -Tpng -o output.png 5 | gprof2dot analysis.txt | dot -Tsvg -o output.svg 6 | -------------------------------------------------------------------------------- /release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | NOTES=$(git --no-pager log --decorate=short --pretty=oneline -n1 --no-color) 4 | CHANGELOG="> $NOTES" 5 | 6 | echo $CHANGELOG > changelog.md 7 | 8 | mkdir -p build 9 | cd build && cmake .. && make -j8 && \ 10 | mkdir -p release && \ 11 | cp glms_e release/. && \ 12 | cp *.a release/. && \ 13 | cp *.so release/. && \ 14 | tar -czf release.tar.gz release/* 15 | 16 | 17 | RELEASE_VERSION=$(date +%s) 18 | 19 | gh release create $RELEASE_VERSION -F ../changelog.md release.tar.gz 20 | -------------------------------------------------------------------------------- /sample/and_and.gs: -------------------------------------------------------------------------------- 1 | for (int i = 0; i < 16; i++) { 2 | if (i > 8 && i < 16) { 3 | print(i); 4 | } 5 | } 6 | 7 | -------------------------------------------------------------------------------- /sample/array.gs: -------------------------------------------------------------------------------- 1 | const arr = [5, 3, 6, 0, 11]; 2 | 3 | 4 | const k = arr[1]; 5 | 6 | 7 | print(k); 8 | -------------------------------------------------------------------------------- /sample/array_includes.gs: -------------------------------------------------------------------------------- 1 | array arr = [5, 3, 7, 0, 10]; 2 | 3 | print(arr.includes(5)); 4 | print(arr.includes(0)); 5 | print(arr.includes(99)); 6 | -------------------------------------------------------------------------------- /sample/assets/somefile.json: -------------------------------------------------------------------------------- 1 | { 2 | "firstName": "John", 3 | "age": 33 4 | } 5 | -------------------------------------------------------------------------------- /sample/basic.gs: -------------------------------------------------------------------------------- 1 | print(x + 2); 2 | -------------------------------------------------------------------------------- /sample/bool.gs: -------------------------------------------------------------------------------- 1 | bool ok = false; 2 | bool ok2 = true; 3 | 4 | print(ok); 5 | print(ok2); 6 | 7 | if (ok) { 8 | print("nooo!"); 9 | } else if (ok2) { 10 | print("yas!"); 11 | } -------------------------------------------------------------------------------- /sample/cantor.gs: -------------------------------------------------------------------------------- 1 | float a = 55; 2 | float b = 100; 3 | 4 | number c = cantor(a, b); 5 | 6 | array d = decant(c); 7 | print(d); 8 | -------------------------------------------------------------------------------- /sample/child.gs: -------------------------------------------------------------------------------- 1 | import "func2.gs" as helpers 2 | 3 | number value = helpers.add(5, 3); 4 | 5 | print(value); 6 | -------------------------------------------------------------------------------- /sample/cos_sin.gs: -------------------------------------------------------------------------------- 1 | number a = cos(1.63124 * random()); 2 | number b = sin(3.33124 * random()); 3 | number c = tan(1.51235 * random()); 4 | 5 | print(a); 6 | print(b); 7 | print(c); 8 | 9 | print(atan(a)); 10 | print(atan(a, b)); 11 | 12 | print(PI); 13 | print(TAU); 14 | 15 | print(fract(PI)); 16 | 17 | vec3 v = vec3(a, b, c); 18 | 19 | print(v); -------------------------------------------------------------------------------- /sample/dot.gs: -------------------------------------------------------------------------------- 1 | vec3 a = vec3(0, 1, 0); 2 | vec3 b = vec3(0, 0.2, 0.8); 3 | number d = dot(a, b); 4 | 5 | print(d); 6 | -------------------------------------------------------------------------------- /sample/emit.glsl: -------------------------------------------------------------------------------- 1 | float test() { 2 | return time <= 0.0 ? 0.0 : 0.5 + 0.5 * cos(time); 3 | } 4 | 5 | 6 | float DistributionGGX(vec3 N, vec3 H, float roughness) 7 | { 8 | float a = roughness*roughness; 9 | float a2 = a*a; 10 | float NdotH = max(dot(N, H), 0.0); 11 | float NdotH2 = NdotH*NdotH; 12 | 13 | float nom = a2; 14 | float denom = (NdotH2 * (a2 - 1.0) + 1.0); 15 | denom = M_PI * denom * denom; 16 | 17 | return nom / notzero(max( denom, 0.000001 )); 18 | } 19 | 20 | vec3 fresnelSchlickRoughness(float NdotV, vec3 F0, float rough) { 21 | return F0 + (max(vec3(1.0 - rough), F0) - F0) * pow(max(1.0 - NdotV, 0.0), 5.0); 22 | } 23 | 24 | /*vec3 fresnelSchlickRoughness(float cosTheta, vec3 F0, float roughness) { 25 | return F0 + (max(vec3(1.0 - roughness), F0) - F0) * 26 | pow(max(1.0 - cosTheta, 0.0), 5.0); 27 | }*/ 28 | 29 | 30 | vec3 EnvBRDFApprox(vec3 specularColor, float roughness, float ndotv) { 31 | const vec4 c0 = vec4(-1, -0.0275, -0.572, 0.022); 32 | const vec4 c1 = vec4(1, 0.0425, 1.04, -0.04); 33 | vec4 r = roughness * c0 + c1; 34 | float a004 = min(r.x * r.x, exp2(-9.28 * ndotv)) * r.x + r.y; 35 | vec2 AB = vec2(-1.04, 1.04) * a004 + r.zw; 36 | return specularColor * AB.x + AB.y; 37 | } 38 | 39 | 40 | vec3 fresnelSchlick(float cosTheta, vec3 F0) 41 | { 42 | return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0); 43 | } 44 | 45 | float GeometrySchlickGGX(float NdotV, float k) 46 | { 47 | float nom = NdotV; 48 | float denom = NdotV * (1.0 - k) + k; 49 | 50 | return nom / notzero(denom); 51 | } 52 | 53 | float GeometrySmith(vec3 N, vec3 V, vec3 L, float k) 54 | { 55 | float NdotV = max(dot(N, V), 0.0); 56 | float NdotL = max(dot(N, L), 0.0); 57 | float ggx1 = GeometrySchlickGGX(NdotV, k); 58 | float ggx2 = GeometrySchlickGGX(NdotL, k); 59 | 60 | return ggx1 * ggx2; 61 | } 62 | 63 | float microfacetDistribution(float roughness, float NdotH) 64 | { 65 | float roughnessSq = roughness * roughness; 66 | float f = (NdotH * roughnessSq - NdotH) * NdotH + 1.0; 67 | return roughnessSq / notzero((M_PI * f * f) + 0.00001); 68 | } 69 | -------------------------------------------------------------------------------- /sample/enum.gs: -------------------------------------------------------------------------------- 1 | typedef enum { 2 | EMOTION_HAPPY, 3 | EMOTION_ANGRY, 4 | EMOTION_SAD 5 | } EmotionState; 6 | 7 | 8 | EmotionState j = EmotionState.EMOTION_ANGRY; 9 | 10 | 11 | switch (j) { 12 | case EmotionState.EMOTION_HAPPY: print("Happy"); break; 13 | case EmotionState.EMOTION_ANGRY: print("Angry"); break; 14 | case EmotionState.EMOTION_SAD: print("Sad"); break; 15 | } 16 | -------------------------------------------------------------------------------- /sample/extension.gs: -------------------------------------------------------------------------------- 1 | import "/home/ianertson/workspace/glms-canvas/build/libglms_canvas.so" as canvasLib; 2 | typedef (canvasLib.canvas) canvas; // we're making a "promise" to the interpreter 3 | // that this type will exist later. 4 | 5 | canvas c = canvas(640, 480); 6 | 7 | // opens a window, changes can be seen in real-time 8 | c.shade((vec3 uv, vec3 fragCoord, vec3 resolution, number time) => { 9 | vec3 p = (uv * 3.912) + vec3(cos(time), sin(time), 0); 10 | float n = fract(cos(p.x + 1.69482 * p.y) * dot(p, vec3(1.2314 + fract(time/1.6), 1.1111, 0))); 11 | return vec4(vec3(n), 1.0); 12 | // return vec4(0.5 * (0.5 + cos(uv.x*time)), 0.5 * (0.5 + sin(uv.y * time)), cos(time), 1.0); 13 | }); 14 | -------------------------------------------------------------------------------- /sample/extension2.gs: -------------------------------------------------------------------------------- 1 | import "/home/ianertson/workspace/glms-canvas/build/libglms_canvas.so" as canvasLib; 2 | typedef (canvasLib.canvas) canvas; // we're making a "promise" to the interpreter 3 | // that this type will exist later. 4 | 5 | 6 | image img = image.load("/home/ianertson/Downloads/london.jpg"); 7 | 8 | canvas c = canvas(640, 480); 9 | // opens a window, changes can be seen in real-time 10 | c.shade((vec3 uv, vec3 fragCoord, vec3 resolution, number time) => { 11 | vec4 px = img.getPixel(fragCoord.x, resolution.y - fragCoord.y); 12 | vec3 col = vec3(px.x / 255, px.y / 255, px.z / 255); 13 | 14 | vec3 col2 = vec3(atan(col.r, cos(time*uv.x)), atan(col.g, sin(time*uv.y)), atan(col.b, tan(time*(uv.x + uv.y)))); 15 | 16 | return vec4(col2, 1.0); 17 | // return vec4(0.5 * (0.5 + cos(uv.x*time)), 0.5 * (0.5 + sin(uv.y * time)), cos(time), 1.0); 18 | }); 19 | -------------------------------------------------------------------------------- /sample/fetch_json.gs: -------------------------------------------------------------------------------- 1 | response r = fetch("https://jsonplaceholder.typicode.com/posts"); 2 | 3 | array p = r.json(); 4 | 5 | int len = p.length(); 6 | for (int i = 0; i < len; i++) { 7 | object post = p[i]; 8 | print(post.title); 9 | } 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /sample/file.gs: -------------------------------------------------------------------------------- 1 | file f = file.open("/home/ianertson/Downloads/bible.txt", "r+"); 2 | 3 | iterator it = f.readLines(); 4 | 5 | 6 | while (string x = it.next()) { 7 | print(x); 8 | } 9 | 10 | f.close(); 11 | -------------------------------------------------------------------------------- /sample/filter.gs: -------------------------------------------------------------------------------- 1 | array arr = [1, 2, 3, 4, 5, 6]; 2 | 3 | array filtered = arr.filter((number v) => v > 2); 4 | 5 | print(filtered); 6 | 7 | -------------------------------------------------------------------------------- /sample/for.gs: -------------------------------------------------------------------------------- 1 | 2 | for (number i = 0; i < 3; i++) { 3 | for (number j = 0; j < 3; j++) { 4 | print(j); 5 | } 6 | 7 | } -------------------------------------------------------------------------------- /sample/func.gs: -------------------------------------------------------------------------------- 1 | print((vec3(1, 2, 3) * 2) + 3 * 5); 2 | -------------------------------------------------------------------------------- /sample/func2.gs: -------------------------------------------------------------------------------- 1 | function add(number x, number y) { 2 | return x + y; 3 | } 4 | -------------------------------------------------------------------------------- /sample/func_glsl_style.gs: -------------------------------------------------------------------------------- 1 | import "func2.gs" as helpers; 2 | import "func2.gs" as helpers; 3 | import "func2.gs" as helpers; 4 | import "func2.gs" as helpers; 5 | import "func2.gs" as helpers; 6 | 7 | glsl` 8 | layout (location = 0) in vec3 attr_vertex; 9 | layout (location = 1) in vec2 attr_uv; 10 | layout (location = 2) in vec3 attr_normal; 11 | ` 12 | 13 | uniform sampler2D myTexture; 14 | 15 | typedef struct { 16 | int on; 17 | int id; 18 | int type; 19 | float strength; 20 | float radius; 21 | vec3 position; 22 | vec3 direction; 23 | vec4 color; 24 | } WELLLight; 25 | 26 | glsl` 27 | layout (std430) readonly buffer storage_lights 28 | { 29 | WELLLight s_lights[]; 30 | }; 31 | ` 32 | void hello() { 33 | add(5.0281, 4); 34 | } 35 | 36 | typedef struct { 37 | vec3 p; 38 | vec3 n; 39 | } Data; 40 | 41 | 42 | for (int i = 0; i < 10; i++) { 43 | print(i); 44 | } 45 | 46 | 47 | void main() { 48 | vec3 col = texture(myTexture, uv); 49 | 50 | float floats[4] = [1, 2, 3, 4]; 51 | 52 | vec3 normal = mat3(transpose(inverse(model))) * attr_normal; 53 | FragColor = vec4(vec3(uv.x, uv.y, 0), 1.0); 54 | } 55 | 56 | -------------------------------------------------------------------------------- /sample/greeting.gs: -------------------------------------------------------------------------------- 1 | const greeting = (msg) => print(msg); 2 | greeting("hello world!"); 3 | -------------------------------------------------------------------------------- /sample/hash_comment.gs: -------------------------------------------------------------------------------- 1 | float test() { 2 | return 3.5; # hash comment 3 | } 4 | 5 | #hash comment 6 | # hash comment 7 | 8 | 9 | ########### 10 | print(test()); ############ 11 | ############ 12 | -------------------------------------------------------------------------------- /sample/image.gs: -------------------------------------------------------------------------------- 1 | number w = 512; 2 | number h = 512; 3 | 4 | 5 | 6 | image g = image.make(w, h); 7 | 8 | 9 | -------------------------------------------------------------------------------- /sample/image2.gs: -------------------------------------------------------------------------------- 1 | number w = 1920; 2 | number h = 1080; 3 | 4 | image img = image.make(w, h); 5 | 6 | img.shade((vec3 uv, vec3 fragCoord, vec3 resolution) => { 7 | // vec3 center = resolution * 0.5; 8 | //number d = abs(distance(fragCoord, center)); 9 | //number g = 255 * (d < TAU * 6.0); 10 | return vec4(255, 0, 0, 255.0); 11 | }); 12 | 13 | img.save("test.png"); 14 | -------------------------------------------------------------------------------- /sample/image3.gs: -------------------------------------------------------------------------------- 1 | number w = 200; 2 | number h = 200; 3 | 4 | image img = image.make(w, h); 5 | 6 | 7 | 8 | img.shade((vec3 uv, vec3 fragCoord, vec3 resolution) => { 9 | vec3 center = resolution * 0.5; 10 | number d = abs(distance(fragCoord, center)); 11 | number g = 255 * (d < TAU * 6.0 * (1.0 + random())); 12 | vec3 color = mix(vec3(0.1, 0.3, 0.9), vec3(1), g); 13 | return vec4(color.xyz, 1.0); 14 | }); 15 | 16 | img.save("test2.png"); 17 | -------------------------------------------------------------------------------- /sample/image4.gs: -------------------------------------------------------------------------------- 1 | number w = 640; 2 | number h = 480; 3 | 4 | image img = image.make(w, h); 5 | 6 | 7 | const noise = (vec3 uv) => { 8 | return fract(cos(uv.x * 2.192 + uv.y) * dot(uv, vec3(1.1245, 0.99181, 0.0))); 9 | }; 10 | 11 | 12 | img.shade((vec3 uv, vec3 fragCoord, vec3 resolution) => { 13 | number g = noise(uv * 10.0) * 255; 14 | return vec4(g, g, g, 255.0); 15 | }); 16 | 17 | img.save("test.png"); 18 | -------------------------------------------------------------------------------- /sample/image_circle.gs: -------------------------------------------------------------------------------- 1 | number w = 640; 2 | number h = 480; 3 | 4 | image img = image.make(w, h); 5 | 6 | function circle(vec3 uv, vec3 pos, number rad, vec3 color) { 7 | number d = length(pos - uv) - rad; 8 | number t = clamp(d, 0.0, 1.0); 9 | return vec4(color, 1.0 - t); 10 | } 11 | 12 | img.shade((vec3 uv, vec3 fragCoord, vec3 resolution) => { 13 | vec3 center = resolution * 0.5; 14 | return circle(fragCoord, center, 0.25 * resolution.y, vec3(1, 0, 0)); 15 | }); 16 | 17 | img.save("circle.png"); 18 | -------------------------------------------------------------------------------- /sample/image_load.gs: -------------------------------------------------------------------------------- 1 | image img = image.load("/home/ianertson/Downloads/london.jpg"); 2 | 3 | print(img.getPixel(0, 0)); 4 | -------------------------------------------------------------------------------- /sample/include/utils.glsl: -------------------------------------------------------------------------------- 1 | float some_util_function(float a, float b) { 2 | return a + b; 3 | } 4 | 5 | vec3 getLightAtt(in Light light, in vec3 p, in vec3 n) { 6 | vec3 L = getLightDir(light, p); 7 | float NdotL = max(0.0015, dot(n, L)); 8 | 9 | switch (light.type) { 10 | case LIGHT_AMBIENT: return light.color * light.strength * NdotL; break; 11 | case LIGHT_POINT: return light.color * NdotL * ( 12 | pow(light.strength, 2.0) / max(0.0001, pow(distance(light.position, p), 2.0)) 13 | ); break; 14 | case LIGHT_DIR: return light.color * light.strength * NdotL * smoothstep(0.8, 1.0, dot( 15 | normalize(light.position - p), 16 | L 17 | )); break; 18 | } 19 | 20 | return vec3(0.0); 21 | } 22 | -------------------------------------------------------------------------------- /sample/int.gs: -------------------------------------------------------------------------------- 1 | int x = 2; 2 | number y = 3; 3 | 4 | print(x + y); 5 | -------------------------------------------------------------------------------- /sample/json.gs: -------------------------------------------------------------------------------- 1 | file f = file.open("assets/somefile.json", "r"); 2 | string contents = f.read(); 3 | f.close(); 4 | 5 | object data = json.parse(contents); 6 | 7 | print(data.firstName); 8 | print(data.age); 9 | -------------------------------------------------------------------------------- /sample/lerp.gs: -------------------------------------------------------------------------------- 1 | number x = 25.012; 2 | number y = 98.241; 3 | 4 | number z = lerp(x, y, 0.1); 5 | 6 | 7 | print(z); 8 | -------------------------------------------------------------------------------- /sample/loop.gs: -------------------------------------------------------------------------------- 1 | number x = 100; 2 | 3 | while (x > 0) { 4 | x--; 5 | } 6 | 7 | print(x); 8 | 9 | 10 | for (number i = 0; i < 3; i++) { 11 | print(i); 12 | } 13 | -------------------------------------------------------------------------------- /sample/map.gs: -------------------------------------------------------------------------------- 1 | array arr = [1, 2, 3]; 2 | 3 | array mapped = arr.map((number v) => v*2); 4 | 5 | print(mapped); 6 | 7 | -------------------------------------------------------------------------------- /sample/material.gs: -------------------------------------------------------------------------------- 1 | typedef struct { 2 | float AO; 3 | float roughness; 4 | float metallic; 5 | vec3 spec; 6 | vec3 normal; 7 | vec4 albedo; 8 | } PBRMaterial; 9 | 10 | void pbr_material_init(inout PBRMaterial m) { 11 | m.AO = 0.0; 12 | m.roughness = 0.0; 13 | m.metallic = 0.0; 14 | m.spec = vec3(0.0); 15 | m.normal = vec3(0.0); 16 | m.albedo = vec4(0.0); 17 | } 18 | -------------------------------------------------------------------------------- /sample/math.gs: -------------------------------------------------------------------------------- 1 | function nilton(vec3 p) { 2 | print(p); 3 | print(p.x *120.0); 4 | } 5 | for (number i = 0; i < 200;i++) { 6 | nilton(vec3(i)); 7 | } 8 | -------------------------------------------------------------------------------- /sample/matrix.gs: -------------------------------------------------------------------------------- 1 | number w = 640; 2 | number h = 480; 3 | number aspect = w / h; 4 | 5 | mat4 model = identity(); 6 | mat4 view = identity(); 7 | mat4 projection = perspective(radians(60.0), aspect, 0.1, 100.0); 8 | 9 | mat4 mvp = projection * view * model; 10 | 11 | vec3 point = vec3(1, 2, 3); 12 | vec4 p = mvp * vec4(point.xyz, 1); 13 | 14 | print(p); 15 | -------------------------------------------------------------------------------- /sample/mul.gs: -------------------------------------------------------------------------------- 1 | number a = cos(0.2415); 2 | 3 | number b = sin(1.5235); 4 | 5 | number p = atan(a, b); 6 | 7 | print(p * 255.0); 8 | -------------------------------------------------------------------------------- /sample/object.gs: -------------------------------------------------------------------------------- 1 | object x = { 2 | "hello": 123, 3 | "nested": { 4 | "yo": 42, 5 | "other": { 6 | name: "John" 7 | } 8 | } 9 | }; 10 | 11 | x.hello = 33; 12 | number y = x.hello; 13 | print(y); 14 | print(x.nested.other.name); 15 | -------------------------------------------------------------------------------- /sample/or.gs: -------------------------------------------------------------------------------- 1 | for (int i = 0; i < 16; i++) { 2 | if ((i > 8 && i < 16) || i == 2) { 3 | print(i); 4 | } 5 | } 6 | 7 | -------------------------------------------------------------------------------- /sample/pbr.gs: -------------------------------------------------------------------------------- 1 | import "material.gs" as i_material; 2 | fdecl PBRMaterial; 3 | 4 | void get_pbr_from_gbuffer(inout PBRMaterial m, in vec3 normal) { 5 | // pbr_material_init(m); 6 | 7 | 8 | float AO = 0.0; 9 | float roughness = 0.0; 10 | float metallic = 0.0; 11 | 12 | if (u_material.arm > 0) { 13 | vec4 i_arm = texture(sampler2D(u_material.arm), uv); 14 | AO = i_arm.x; 15 | roughness = i_arm.y; 16 | metallic = i_arm.z; 17 | } else if (u_material.rough > 0) { 18 | vec4 i_rough = texture(sampler2D(u_material.rough), uv); 19 | AO = i_rough.x; 20 | roughness = i_rough.y; 21 | metallic = i_rough.z; 22 | } else if (u_material.AO > 0) { 23 | vec4 i_AO = texture(sampler2D(u_material.AO), uv); 24 | AO = i_AO.x; 25 | } 26 | 27 | vec3 n = normalize(normal); 28 | vec4 i_bump = texture(sampler2D(u_material.normal), uv); 29 | vec4 i_albedo = texture(sampler2D(u_material.albedo), uv); 30 | vec4 i_spec = texture(sampler2D(u_material.spec), uv); 31 | 32 | 33 | 34 | m.AO = AO; 35 | m.roughness = roughness; 36 | m.metallic = metallic; 37 | m.spec = i_spec.rgb; 38 | m.normal = normalize(n + 0.25*normalize(i_bump.xyz)); 39 | m.albedo = i_albedo; 40 | } 41 | -------------------------------------------------------------------------------- /sample/pow.gs: -------------------------------------------------------------------------------- 1 | number x = pow(3.5, 7.1); 2 | 3 | print(x); 4 | -------------------------------------------------------------------------------- /sample/print.gs: -------------------------------------------------------------------------------- 1 | print("hello"); 2 | -------------------------------------------------------------------------------- /sample/quat.gs: -------------------------------------------------------------------------------- 1 | vec4 q = quatFor(vec3(-1, 0, 0), vec3(0, 1, 0)); 2 | 3 | 4 | vec3 p = vec3(1); 5 | 6 | vec4 n = vec4(p, 1.0) * q; 7 | -------------------------------------------------------------------------------- /sample/reassign.gs: -------------------------------------------------------------------------------- 1 | int i = 2; 2 | 3 | i /= 3.6; 4 | print(i); 5 | -------------------------------------------------------------------------------- /sample/self.gs: -------------------------------------------------------------------------------- 1 | typedef struct { 2 | string name; 3 | 4 | function changeName(string newName) { 5 | self.name = newName; 6 | } 7 | } Person; 8 | 9 | 10 | Person p = Person("John Doe"); 11 | 12 | print(p.name); 13 | 14 | p.changeName("David Doe"); 15 | 16 | print(p.name); 17 | -------------------------------------------------------------------------------- /sample/smoothstep.gs: -------------------------------------------------------------------------------- 1 | vec3 a = vec3(0, 0.1, 0.2); 2 | vec3 b = vec3(4, 5, 6); 3 | 4 | vec3 c = smoothstep(a, b, 0.5); 5 | vec3 d = smoothstep(a, b, vec3(random(), random(), random())); 6 | 7 | print(c); 8 | print(d); 9 | -------------------------------------------------------------------------------- /sample/sort.gs: -------------------------------------------------------------------------------- 1 | array arr = [5, 1, 3, 9, 2]; 2 | 3 | array sorted = arr.sort((number a, number b) => { 4 | return a > b; 5 | }); 6 | 7 | print(sorted); 8 | 9 | -------------------------------------------------------------------------------- /sample/string.gs: -------------------------------------------------------------------------------- 1 | string firstname = "John"; 2 | string lastname = "Doe"; 3 | 4 | string fullname = firstname + " " + lastname; 5 | 6 | print(fullname); 7 | 8 | 9 | string replaced = fullname.replace("John", "David"); 10 | 11 | print(replaced); 12 | -------------------------------------------------------------------------------- /sample/string_includes.gs: -------------------------------------------------------------------------------- 1 | string name = "John Doe"; 2 | 3 | print(name.includes("John")); 4 | print(name.includes("Doe")); 5 | print(name.includes("test")); 6 | -------------------------------------------------------------------------------- /sample/struct.gs: -------------------------------------------------------------------------------- 1 | typedef struct { 2 | number age = 2; 3 | string name; 4 | } Person; 5 | 6 | Person p = Person(33, "John Doe"); 7 | 8 | print(p.age); 9 | print(p.name); 10 | -------------------------------------------------------------------------------- /sample/structfunc.gs: -------------------------------------------------------------------------------- 1 | typedef struct { 2 | function bark() { 3 | print("Woof woof!"); 4 | } 5 | } Dog; 6 | 7 | Dog dog = Dog(); 8 | 9 | dog.bark(); 10 | -------------------------------------------------------------------------------- /sample/template_string.gs: -------------------------------------------------------------------------------- 1 | string name = "John"; 2 | string x = `hello ${name}`; 3 | 4 | print(x); 5 | -------------------------------------------------------------------------------- /sample/test.gs: -------------------------------------------------------------------------------- 1 | const x = 123; 2 | 3 | 4 | if (x) { 5 | print("Truthy!"); 6 | } else { 7 | print("False!"); 8 | } 9 | -------------------------------------------------------------------------------- /sample/uint64.gs: -------------------------------------------------------------------------------- 1 | uint64_t p = 32312; 2 | print(p); 3 | -------------------------------------------------------------------------------- /sample/use_include.gs: -------------------------------------------------------------------------------- 1 | include "include/utils.glsl"; 2 | 3 | 4 | void main() { 5 | float x = some_util_function(5, 3); 6 | } 7 | -------------------------------------------------------------------------------- /sample/vec.gs: -------------------------------------------------------------------------------- 1 | vec3 a = vec3(1, 2, 3); 2 | vec3 b = vec3(3, 4, 6); 3 | 4 | vec3 c = b - a; 5 | 6 | print(c); 7 | -------------------------------------------------------------------------------- /src/allocator.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | // TODO: use some kind of arena for these strings 8 | 9 | char* glms_allocator_string_allocator_strdup(void* user_ptr, const char* s) { 10 | return strdup(s); 11 | } 12 | 13 | void glms_allocator_string_allocator_strcat(void* user_ptr, char** instr, 14 | const char* append) { 15 | text_append(instr, append); 16 | } 17 | 18 | void glms_allocator_string_allocator(GLMSAllocator* alloc) { 19 | if (!alloc) return; 20 | alloc->strdup = glms_allocator_string_allocator_strdup; 21 | alloc->strcat = glms_allocator_string_allocator_strcat; 22 | alloc->func = 0; 23 | } 24 | -------------------------------------------------------------------------------- /src/ast_to_string.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "glms/ast_type.h" 8 | #include "glms/string_view.h" 9 | 10 | char* glms_ast_to_string(GLMSAST ast, GLMSAllocator alloc, 11 | struct GLMS_ENV_STRUCT* env) { 12 | GLMSAST* t = glms_env_get_type_for(env, &ast); 13 | 14 | if (t && t->to_string) { 15 | return t->to_string(&ast, alloc, env); 16 | } 17 | 18 | if (!alloc.strdup) GLMS_WARNING_RETURN(0, stderr, "No allocator provided.\n"); 19 | if (ast.to_string) { 20 | return ast.to_string(&ast, alloc, env); 21 | } 22 | 23 | switch (ast.type) { 24 | case GLMS_AST_TYPE_BOOL: { 25 | return alloc.strdup(alloc.user_ptr, ast.as.boolean ? "true" : "false"); 26 | }; break; 27 | case GLMS_AST_TYPE_STACK_PTR: { 28 | GLMSAST* ptr = 0; 29 | if ((ptr = glms_ast_get_ptr(ast))) { 30 | return glms_ast_to_string(*ptr, alloc, env); 31 | } 32 | }; break; 33 | case GLMS_AST_TYPE_STACK: { 34 | char* s = 0; 35 | 36 | HashyIterator it = {0}; 37 | while (hashy_map_iterate(&ast.as.stack.env->types, &it)) { 38 | if (!it.bucket->is_set) continue; 39 | if (!it.bucket->value) continue; 40 | 41 | const char* key = it.bucket->key.value; 42 | GLMSAST* value = (GLMSAST*)it.bucket->value; 43 | 44 | char* strval = glms_ast_to_string(*value, alloc, env); 45 | 46 | if (!strval) continue; 47 | alloc.strcat(alloc.user_ptr, &s, key); 48 | alloc.strcat(alloc.user_ptr, &s, " => "); 49 | alloc.strcat(alloc.user_ptr, &s, strval); 50 | alloc.strcat(alloc.user_ptr, &s, "\n"); 51 | } 52 | 53 | HashyIterator it2 = {0}; 54 | while (hashy_map_iterate(&ast.as.stack.env->globals, &it2)) { 55 | if (!it2.bucket->is_set) continue; 56 | if (!it2.bucket->value) continue; 57 | 58 | const char* key = it2.bucket->key.value; 59 | GLMSAST* value = (GLMSAST*)it2.bucket->value; 60 | 61 | char* strval = glms_ast_to_string(*value, alloc, env); 62 | 63 | if (!strval) continue; 64 | alloc.strcat(alloc.user_ptr, &s, key); 65 | alloc.strcat(alloc.user_ptr, &s, " => "); 66 | alloc.strcat(alloc.user_ptr, &s, strval); 67 | alloc.strcat(alloc.user_ptr, &s, "\n"); 68 | } 69 | 70 | if (!s) return strdup(GLMS_AST_TYPE_STR[ast.type]); 71 | 72 | return s; 73 | 74 | }; break; 75 | case GLMS_AST_TYPE_STRUCT: { 76 | HashyIterator it = {0}; 77 | char* s = 0; 78 | 79 | if (ast.props.initialized) { 80 | while (hashy_map_iterate(&ast.props, &it)) { 81 | if (!it.bucket->is_set) continue; 82 | if (!it.bucket->value) continue; 83 | 84 | const char* key = it.bucket->key.value; 85 | GLMSAST* value = (GLMSAST*)it.bucket->value; 86 | 87 | char* strval = glms_ast_to_string(*value, alloc, env); 88 | 89 | if (!strval) continue; 90 | alloc.strcat(alloc.user_ptr, &s, key); 91 | alloc.strcat(alloc.user_ptr, &s, " => "); 92 | alloc.strcat(alloc.user_ptr, &s, strval); 93 | alloc.strcat(alloc.user_ptr, &s, "\n"); 94 | } 95 | } 96 | 97 | if (s) return s; 98 | 99 | return alloc.strdup(alloc.user_ptr, GLMS_AST_TYPE_STR[ast.type]); 100 | }; break; 101 | case GLMS_AST_TYPE_STRING: { 102 | const char* v = glms_string_view_get_value(&ast.as.string.value); 103 | if (v != 0) { 104 | return alloc.strdup(alloc.user_ptr, v); 105 | } 106 | }; break; 107 | case GLMS_AST_TYPE_NUMBER: { 108 | char tmp[256]; 109 | sprintf(tmp, "%1.6f", glms_ast_number(ast)); 110 | return alloc.strdup(alloc.user_ptr, tmp); 111 | }; break; 112 | default: { 113 | if (ast.json != 0) { 114 | char* jsonstr = json_stringify(ast.json); 115 | if (jsonstr) return jsonstr; 116 | } 117 | return alloc.strdup(alloc.user_ptr, GLMS_AST_TYPE_STR[ast.type]); 118 | }; break; 119 | } 120 | 121 | return 0; 122 | } 123 | 124 | char* glms_ast_to_string_debug_binop(GLMSAST ast) { 125 | char* s = 0; 126 | text_append(&s, glms_ast_to_string_debug(*ast.as.binop.left)); 127 | text_append(&s, " "); 128 | text_append(&s, GLMS_TOKEN_TYPE_STR[ast.as.binop.op]); 129 | text_append(&s, " "); 130 | text_append(&s, glms_ast_to_string_debug(*ast.as.binop.right)); 131 | return s; 132 | } 133 | char* glms_ast_to_string_debug_unop(GLMSAST ast) { 134 | char* s = 0; 135 | 136 | if (ast.as.unop.left) { 137 | text_append(&s, glms_ast_to_string_debug(*ast.as.unop.left)); 138 | } 139 | text_append(&s, GLMS_TOKEN_TYPE_STR[ast.as.unop.op]); 140 | 141 | if (ast.as.unop.right) { 142 | text_append(&s, glms_ast_to_string_debug(*ast.as.unop.right)); 143 | } 144 | return s; 145 | } 146 | char* glms_ast_to_string_debug_id(GLMSAST ast) { 147 | const char* strval = glms_string_view_get_value(&ast.as.id.value); 148 | return strdup(OR(strval, "(null)")); 149 | } 150 | char* glms_ast_to_string_debug_string(GLMSAST ast) { 151 | const char* strval = glms_string_view_get_value(&ast.as.string.value); 152 | return strdup(OR(strval, "(null)")); 153 | } 154 | char* glms_ast_to_string_debug_number(GLMSAST ast) { 155 | char tmp[256]; 156 | sprintf(tmp, "%1.6f", glms_ast_number(ast)); 157 | return strdup(tmp); 158 | } 159 | 160 | static char* glms_ast_to_string_debug_(GLMSAST ast) { 161 | switch (ast.type) { 162 | case GLMS_AST_TYPE_BINOP: { 163 | return glms_ast_to_string_debug_binop(ast); 164 | }; break; 165 | case GLMS_AST_TYPE_UNOP: { 166 | return glms_ast_to_string_debug_unop(ast); 167 | }; break; 168 | case GLMS_AST_TYPE_ID: { 169 | return glms_ast_to_string_debug_id(ast); 170 | }; break; 171 | case GLMS_AST_TYPE_STRING: { 172 | return glms_ast_to_string_debug_string(ast); 173 | }; break; 174 | case GLMS_AST_TYPE_NUMBER: { 175 | return glms_ast_to_string_debug_number(ast); 176 | }; break; 177 | default: { 178 | return strdup(GLMS_AST_TYPE_STR[ast.type]); 179 | }; break; 180 | } 181 | } 182 | char* glms_ast_to_string_debug(GLMSAST ast) { 183 | char* ast_str = glms_ast_to_string_debug_(ast); 184 | 185 | char* s = 0; 186 | text_append(&s, GLMS_AST_TYPE_STR[ast.type]); 187 | text_append(&s, "(\n"); 188 | text_append(&s, ast_str ? ast_str : "?"); 189 | text_append(&s, "\n)"); 190 | 191 | return s; 192 | } 193 | -------------------------------------------------------------------------------- /src/dl.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "glms/env.h" 8 | 9 | void* glms_load_symbol(const char* filename, const char* funcname) { 10 | void* handle; 11 | char* error; 12 | void* fptr = 0; 13 | 14 | // /lib/x86_64-linux-gnu/libc.so.6" 15 | 16 | handle = dlopen(filename, RTLD_LAZY); 17 | if (!handle) { 18 | fprintf(stderr, "%s\n", dlerror()); 19 | exit(1); 20 | } 21 | 22 | dlerror(); 23 | 24 | void* ptr = dlsym(handle, funcname); 25 | 26 | if ((error = dlerror()) != NULL) { 27 | GLMS_WARNING_RETURN(0, stderr, "%s\n", error); 28 | } 29 | 30 | return ptr; 31 | } 32 | 33 | GLMSExtensionEntryFunc glms_load_symbol_function(const char* filename, 34 | const char* funcname) { 35 | void* handle; 36 | char* error; 37 | GLMSExtensionEntryFunc fptr = 0; 38 | 39 | // /lib/x86_64-linux-gnu/libc.so.6" 40 | 41 | handle = dlopen(filename, RTLD_LAZY); 42 | if (!handle) { 43 | fprintf(stderr, "%s\n", dlerror()); 44 | exit(1); 45 | } 46 | 47 | dlerror(); 48 | 49 | *(void**)(&fptr) = dlsym(handle, funcname); 50 | 51 | if ((error = dlerror()) != NULL) { 52 | GLMS_WARNING_RETURN(0, stderr, "%s\n", error); 53 | } 54 | 55 | return fptr; 56 | } 57 | -------------------------------------------------------------------------------- /src/emit/emit.c: -------------------------------------------------------------------------------- 1 | #include "glms/env.h" 2 | #include "glms/macros.h" 3 | #include "glms/string_builder.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | int glms_emit_init(GLMSEmit *emit, GLMSEnv* env, GLMSEmitConfig cfg) { 10 | if (emit->initialized) return 1; 11 | if (cfg.mode == GLMS_EMIT_MODE_UNDEFINED) return 0; 12 | if (env == 0) return 0; 13 | 14 | emit->env = env; 15 | 16 | emit->config = cfg; 17 | glms_string_builder_destroy(&emit->builder); 18 | 19 | emit->initialized = true; 20 | 21 | return 1; 22 | } 23 | 24 | int glms_emit_destroy(GLMSEmit *emit) { 25 | if (!emit || !emit->initialized) return 0; 26 | glms_string_builder_destroy(&emit->builder); 27 | emit->initialized = false; 28 | return 1; 29 | } 30 | 31 | int glms_emit(GLMSEmit *emit, GLMSAST *ast) { 32 | if (!emit || !ast || emit->config.mode == GLMS_EMIT_MODE_UNDEFINED) return 0; 33 | 34 | switch (emit->config.mode) { 35 | case GLMS_EMIT_MODE_GLSL: if (!glms_emit_glsl(emit, ast)) return 0; break; 36 | default: { GLMS_WARNING_RETURN(0, stderr, "Invalid emit mode.\n"); }; break; 37 | } 38 | 39 | 40 | if (!emit->builder.buffer || emit->builder.length <= 0) return 0; 41 | const char* path = emit->config.out_path; 42 | if (!path) return 1; 43 | 44 | 45 | FILE* fp = fopen(path, "w+"); 46 | 47 | if (!fp) GLMS_WARNING_RETURN(0, stderr, "Failed to open `%s`.\n", path); 48 | 49 | fwrite(&emit->builder.buffer[0], sizeof(char), emit->builder.length, fp); 50 | 51 | const char* newline = "\n"; 52 | fwrite(&newline[0], sizeof(char), 1, fp); 53 | 54 | fclose(fp); 55 | 56 | 57 | return 1; 58 | } 59 | -------------------------------------------------------------------------------- /src/glms.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sebbekarlsson/glms/bcd54bccd237965cdd341055cc845768309d0177/src/glms.c -------------------------------------------------------------------------------- /src/io.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | bool glms_file_exists(const char* path) { return access(path, F_OK) == 0; } 8 | 9 | char* glms_get_file_contents(const char* filepath) { 10 | if (!glms_file_exists(filepath)) { 11 | fprintf(stderr, "Error: No such file %s\n", filepath); 12 | return 0; 13 | } 14 | FILE* fp = fopen(filepath, "r"); 15 | char* buffer = NULL; 16 | size_t len; 17 | ssize_t bytes_read = getdelim(&buffer, &len, '\0', fp); 18 | if (bytes_read == -1) { 19 | printf("Failed to read file `%s`\n", filepath); 20 | return 0; 21 | } 22 | 23 | fclose(fp); 24 | 25 | return buffer; 26 | } 27 | -------------------------------------------------------------------------------- /src/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "glms/emit/emit.h" 11 | #include "glms/env.h" 12 | 13 | typedef enum { 14 | CLI_ARG_BOOLEAN, 15 | CLI_ARG_STRING 16 | } CLIArgType; 17 | 18 | typedef struct { 19 | union { 20 | bool boolean; 21 | const char* str; 22 | } as; 23 | CLIArgType type; 24 | } CLIArg; 25 | 26 | typedef struct { 27 | HashyMap args; 28 | bool initialized; 29 | } CLIArgs; 30 | 31 | int cli_args_init(CLIArgs* args, int argc, char* argv[]) { 32 | if (args->initialized) return 1; 33 | args->initialized = true; 34 | hashy_map_init(&args->args, (HashyConfig){ .capacity = 16, .free_values_on_destroy = true }); 35 | 36 | for (int i = 0; i < argc; i++) { 37 | CLIArg* carg = NEW(CLIArg); 38 | 39 | const char* key = argv[i]; 40 | int64_t len = strlen(key); 41 | if (len > 2 && ((i+1) < argc) && key[0] == '-' && key[1] == '-') { 42 | const char* value = argv[i+1]; 43 | carg->type = CLI_ARG_STRING; 44 | carg->as.str = value; 45 | hashy_map_set(&args->args, argv[i], carg); 46 | i++; 47 | continue; 48 | } 49 | 50 | carg->type = CLI_ARG_BOOLEAN; 51 | hashy_map_set(&args->args, argv[i], carg); 52 | } 53 | 54 | return 1; 55 | } 56 | 57 | bool cli_args_has(CLIArgs* args, const char* key) { 58 | if (!args->initialized) return false; 59 | return hashy_map_get(&args->args, key) != 0; 60 | } 61 | 62 | const char* cli_args_get_string(CLIArgs* args, const char* key) { 63 | if (!args->initialized) return false; 64 | CLIArg* arg = (CLIArg*)hashy_map_get(&args->args, key); 65 | if (!arg || arg->type != CLI_ARG_STRING) return 0; 66 | return arg->as.str; 67 | } 68 | 69 | int cli_args_destroy(CLIArgs* args) { 70 | if (!args->initialized) return 0; 71 | hashy_map_clear(&args->args); 72 | hashy_map_destroy(&args->args); 73 | return 1; 74 | } 75 | 76 | static int glms_interactive(GLMSConfig cfg) { 77 | GLMSEnv env = {0}; 78 | glms_env_init(&env, 0, 0, cfg); 79 | while (true) { 80 | char input_source[1024]; 81 | memset(&input_source[0], 0, 1024 * sizeof(char)); 82 | 83 | printf("> "); 84 | fgets(input_source, 1024, stdin); 85 | fflush(stdin); 86 | 87 | glms_env_exec_source(&env, input_source); 88 | glms_env_reset(&env); 89 | } 90 | 91 | glms_env_clear(&env); 92 | return 0; 93 | } 94 | 95 | int main(int argc, char* argv[]) { 96 | GLMSConfig cfg = {0}; 97 | if (argc < 2) return glms_interactive(cfg); 98 | 99 | CLIArgs cli = {0}; 100 | cli_args_init(&cli, argc, argv); 101 | 102 | if (cli_args_has(&cli, "--export-docs")) { 103 | GLMSEnv env = {0}; 104 | glms_env_init(&env, 0, argv[1], (GLMSConfig){0}); 105 | glms_env_export_docstrings(&env, "signatures.md"); 106 | glms_env_clear(&env); 107 | cli_args_destroy(&cli); 108 | return 0; 109 | } else if (cli_args_has(&cli, "--version")) { 110 | printf("GLMS Version %s\n", GLMS_VERSION_STRING); 111 | return 0; 112 | } 113 | 114 | char* source = glms_get_file_contents(argv[1]); 115 | if (!source) { 116 | cli_args_destroy(&cli); 117 | return 0; 118 | } 119 | 120 | if (cli_args_has(&cli, "--emit")) { 121 | cfg.emit.out_path = cli_args_get_string(&cli, "--emit"); 122 | cfg.emit.mode = GLMS_EMIT_MODE_GLSL; // TODO: add support for other emit modes. 123 | } 124 | 125 | GLMSEnv env = {0}; 126 | glms_env_init(&env, source, argv[1], cfg); 127 | glms_env_exec(&env); 128 | glms_env_clear(&env); 129 | 130 | free(source); 131 | source = 0; 132 | 133 | cli_args_destroy(&cli); 134 | return 0; 135 | } 136 | -------------------------------------------------------------------------------- /src/math.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | float glms_smoothstep_factor(float edge0, float edge1, float x) { 5 | x = mif_clamp((x - edge0) / (edge1 - edge0), 0.0f, 1.0f); 6 | return x * x * (3 - 2 * x); 7 | } 8 | Vector3 glms_smoothstep_vec3_factor(Vector3 edge0, Vector3 edge1, float f) { 9 | float x = glms_smoothstep_factor(edge0.x, edge1.x, f); 10 | float y = glms_smoothstep_factor(edge0.y, edge1.y, f); 11 | float z = glms_smoothstep_factor(edge0.z, edge1.z, f); 12 | 13 | return VEC3(x, y, z); 14 | } 15 | Vector3 glms_smoothstep_vec3_vec3(Vector3 edge0, Vector3 edge1, Vector3 v) { 16 | float x = glms_smoothstep_factor(edge0.x, edge1.x, v.x); 17 | float y = glms_smoothstep_factor(edge0.y, edge1.y, v.y); 18 | float z = glms_smoothstep_factor(edge0.z, edge1.z, v.z); 19 | 20 | return VEC3(x, y, z); 21 | } 22 | -------------------------------------------------------------------------------- /src/modules/array.c: -------------------------------------------------------------------------------- 1 | #include "glms/allocator.h" 2 | #include "glms/ast.h" 3 | #include "glms/ast_type.h" 4 | #include "glms/env.h" 5 | #include "glms/eval.h" 6 | #include 7 | 8 | // typedef char* (*GLMSASTToString)(struct GLMS_AST_STRUCT *ast, GLMSAllocator alloc); 9 | 10 | char *glms_array_to_string(GLMSAST *ast, GLMSAllocator alloc, GLMSEnv* env) { 11 | char* s = 0; 12 | alloc.strcat(alloc.user_ptr, &s, "["); 13 | 14 | if (ast->children != 0 && ast->children->length > 0) { 15 | for (int64_t i = 0; i < ast->children->length; i++) { 16 | GLMSAST* child = ast->children->items[i]; 17 | char* childstr = glms_ast_to_string(*child, alloc, env); 18 | if (childstr == 0) continue; 19 | alloc.strcat(alloc.user_ptr, &s, childstr); 20 | 21 | if (i < ast->children->length-1) { 22 | alloc.strcat(alloc.user_ptr, &s, ", "); 23 | } 24 | } 25 | } 26 | 27 | alloc.strcat(alloc.user_ptr, &s, "]"); 28 | 29 | return s; 30 | } 31 | 32 | int glms_array_fptr_map(GLMSEval *eval, GLMSAST *ast, GLMSASTBuffer *args, 33 | GLMSStack *stack, GLMSAST *out) { 34 | 35 | if (!glms_eval_expect(eval, stack, (GLMSASTType[]){ GLMS_AST_TYPE_FUNC }, 1, args)) return 0; 36 | 37 | 38 | GLMSAST* new_array = glms_env_new_ast(eval->env, GLMS_AST_TYPE_ARRAY, true); 39 | 40 | GLMSAST ptr = (GLMSAST){ .type = GLMS_AST_TYPE_STACK_PTR, .as.stackptr.ptr = new_array }; 41 | 42 | if (!ast->children || ast->children->length <= 0) { 43 | *out = ptr; 44 | return 1; 45 | } 46 | 47 | 48 | GLMSAST func = args->items[0]; 49 | 50 | for (int64_t i = 0; i < ast->children->length; i++) { 51 | 52 | GLMSAST* val = ast->children->items[i]; 53 | 54 | GLMSASTBuffer call_args = (GLMSASTBuffer){ 55 | .initialized = true, 56 | .items = (GLMSAST[]){ *val }, 57 | .length = 1 58 | }; 59 | 60 | GLMSAST mapped = glms_eval(eval, glms_eval_call_func(eval, stack, &func, call_args), stack); 61 | 62 | glms_ast_push(new_array, glms_ast_copy(mapped, eval->env)); 63 | } 64 | 65 | 66 | ptr.as.stackptr.ptr = new_array; 67 | 68 | *out = ptr; 69 | 70 | return 1; 71 | } 72 | 73 | int glms_array_fptr_filter(GLMSEval *eval, GLMSAST *ast, GLMSASTBuffer *args, 74 | GLMSStack *stack, GLMSAST *out) { 75 | 76 | if (!glms_eval_expect(eval, stack, (GLMSASTType[]){ GLMS_AST_TYPE_FUNC }, 1, args)) return 0; 77 | 78 | 79 | GLMSAST* new_array = glms_env_new_ast(eval->env, GLMS_AST_TYPE_ARRAY, true); 80 | 81 | GLMSAST ptr = (GLMSAST){ .type = GLMS_AST_TYPE_STACK_PTR, .as.stackptr.ptr = new_array }; 82 | 83 | if (!ast->children || ast->children->length <= 0) { 84 | *out = ptr; 85 | return 1; 86 | } 87 | 88 | 89 | GLMSAST func = args->items[0]; 90 | 91 | for (int64_t i = 0; i < ast->children->length; i++) { 92 | 93 | GLMSAST* val = ast->children->items[i]; 94 | 95 | GLMSASTBuffer call_args = (GLMSASTBuffer){ 96 | .initialized = true, 97 | .items = (GLMSAST[]){ *val }, 98 | .length = 1 99 | }; 100 | 101 | GLMSAST result = glms_eval(eval, glms_eval_call_func(eval, stack, &func, call_args), stack); 102 | 103 | if (glms_ast_is_truthy(result)) { 104 | glms_ast_push(new_array, val); 105 | } 106 | } 107 | 108 | 109 | ptr.as.stackptr.ptr = new_array; 110 | 111 | *out = ptr; 112 | 113 | return 1; 114 | } 115 | 116 | int glms_array_fptr_sort(GLMSEval *eval, GLMSAST *ast, GLMSASTBuffer *args, 117 | GLMSStack *stack, GLMSAST *out) { 118 | 119 | if (!glms_eval_expect(eval, stack, (GLMSASTType[]){ GLMS_AST_TYPE_FUNC }, 1, args)) return 0; 120 | 121 | 122 | GLMSAST* new_array = glms_ast_copy(*ast, eval->env); 123 | 124 | GLMSAST ptr = (GLMSAST){ .type = GLMS_AST_TYPE_STACK_PTR, .as.stackptr.ptr = new_array }; 125 | 126 | if (!ast->children || ast->children->length <= 0) { 127 | *out = ptr; 128 | return 1; 129 | } 130 | 131 | GLMSAST func = args->items[0]; 132 | 133 | int64_t n = ast->children->length; 134 | 135 | for (int64_t c = 0; c < n-1; c++) { 136 | 137 | for (int64_t d = 0; d < n - c - 1; d++) { 138 | GLMSASTBuffer call_args = (GLMSASTBuffer){ 139 | .initialized = true, 140 | .items = (GLMSAST[]){ *new_array->children->items[d], *new_array->children->items[d+1] }, 141 | .length = 2 142 | }; 143 | 144 | GLMSAST result = glms_eval(eval, glms_eval_call_func(eval, stack, &func, call_args), stack); 145 | 146 | if (glms_ast_is_truthy(result)) { 147 | GLMSAST* swap = new_array->children->items[d]; 148 | new_array->children->items[d] = new_array->children->items[d+1]; 149 | new_array->children->items[d+1] = swap; 150 | } 151 | } 152 | } 153 | 154 | 155 | ptr.as.stackptr.ptr = new_array; 156 | 157 | *out = ptr; 158 | 159 | return 1; 160 | } 161 | 162 | int glms_array_fptr_push(GLMSEval *eval, GLMSAST *ast, GLMSASTBuffer *args, 163 | GLMSStack *stack, GLMSAST *out) { 164 | 165 | if (!args || args->length <= 0) return 0; 166 | 167 | for (int64_t i = 0; i < args->length; i++) { 168 | GLMSAST arg = args->items[i]; 169 | GLMSAST* copy = glms_ast_copy(arg, eval->env); 170 | glms_ast_push(ast, copy); 171 | } 172 | 173 | return 1; 174 | } 175 | 176 | int glms_array_fptr_length(GLMSEval *eval, GLMSAST *ast, GLMSASTBuffer *args, 177 | GLMSStack *stack, GLMSAST *out) { 178 | 179 | int64_t len = ast->children ? ast->children->length : 0; 180 | *out = (GLMSAST){ .type = GLMS_AST_TYPE_NUMBER, .as.number.value = (float)len }; 181 | return 1; 182 | } 183 | 184 | int glms_array_fptr_includes(GLMSEval *eval, GLMSAST *ast, GLMSASTBuffer *args, 185 | GLMSStack *stack, GLMSAST *out) { 186 | 187 | int64_t len = ast->children ? ast->children->length : 0; 188 | 189 | if (len <= 0 || (args == 0 || args->length <= 0 || args->items == 0)) { 190 | *out = (GLMSAST){ .type = GLMS_AST_TYPE_BOOL, .as.boolean = false }; 191 | return 1; 192 | } 193 | 194 | 195 | GLMSAST compare = args->items[0]; 196 | 197 | for (int64_t i = 0; i < len; i++) { 198 | GLMSAST* child = ast->children->items[i]; 199 | 200 | if (glms_ast_compare_equals_equals(*child, compare)) { 201 | *out = (GLMSAST){ .type = GLMS_AST_TYPE_BOOL, .as.boolean = true }; 202 | return 1; 203 | } 204 | } 205 | 206 | *out = (GLMSAST){ .type = GLMS_AST_TYPE_BOOL, .as.boolean = false }; 207 | 208 | return 1; 209 | } 210 | 211 | void glms_array_constructor(GLMSEval *eval, GLMSStack *stack, 212 | GLMSASTBuffer *args, GLMSAST *self) { 213 | 214 | if (!self) return; 215 | self->type = GLMS_AST_TYPE_ARRAY; 216 | self->constructor = glms_array_constructor; 217 | self->to_string = glms_array_to_string; 218 | glms_ast_register_function(eval->env, self, "map", glms_array_fptr_map); 219 | glms_ast_register_function(eval->env, self, "filter", glms_array_fptr_filter); 220 | glms_ast_register_function(eval->env, self, "sort", glms_array_fptr_sort); 221 | glms_ast_register_function(eval->env, self, "push", glms_array_fptr_push); 222 | glms_ast_register_function(eval->env, self, "length", glms_array_fptr_length); 223 | glms_ast_register_function(eval->env, self, "count", glms_array_fptr_length); 224 | glms_ast_register_function(eval->env, self, "includes", glms_array_fptr_includes); 225 | } 226 | 227 | void glms_array_type(GLMSEnv *env) { 228 | GLMSAST* t = glms_env_new_ast(env, GLMS_AST_TYPE_ARRAY, false); 229 | glms_env_register_type(env, "array", t, glms_array_constructor, 0, glms_array_to_string, 0); 230 | glms_env_register_type(env, GLMS_AST_TYPE_STR[GLMS_AST_TYPE_ARRAY], t, glms_array_constructor, 0, glms_array_to_string, 0); 231 | } 232 | -------------------------------------------------------------------------------- /src/modules/fetch.c: -------------------------------------------------------------------------------- 1 | #include "fastjson/json.h" 2 | #include "fastjson/options.h" 3 | #include "glms/ast.h" 4 | #include "glms/ast_type.h" 5 | #include "glms/env.h" 6 | #include "glms/eval.h" 7 | #include "glms/type.h" 8 | #include 9 | #include 10 | #include 11 | 12 | typedef struct { 13 | char* data; 14 | int64_t len; 15 | int64_t code; 16 | } GLMSFetchResponse; 17 | 18 | char *glms_response_to_string(GLMSAST *ast, GLMSAllocator alloc, GLMSEnv *env) { 19 | GLMSFetchResponse* response = ast->ptr ? (GLMSFetchResponse*)ast->ptr : 0; 20 | 21 | if (response != 0 && response->data == 0) return alloc.strdup(alloc.user_ptr, "(null)"); 22 | 23 | char tmp[256]; 24 | sprintf(tmp, "Response<%ld>", response ? response->code : 0); 25 | 26 | return alloc.strdup(alloc.user_ptr, tmp); 27 | } 28 | 29 | void glms_response_destructor(GLMSAST *ast) { 30 | if (!ast) 31 | return; 32 | 33 | if (!ast->ptr) 34 | return; 35 | 36 | GLMSFetchResponse* response = (GLMSFetchResponse*)ast->ptr; 37 | 38 | if (response->data != 0) { 39 | free(response->data); 40 | response->data = 0; 41 | } 42 | 43 | response->code = 0; 44 | response->len = 0; 45 | 46 | free(response); 47 | 48 | ast->ptr = 0; 49 | } 50 | 51 | static size_t writefunc(void *ptr, size_t size, size_t nmemb, GLMSFetchResponse *response) 52 | { 53 | size_t new_len = response->len + size*nmemb; 54 | response->data = realloc(response->data, new_len+1); 55 | 56 | if (response->data == NULL) 57 | { 58 | GLMS_WARNING_RETURN(0, stderr, "failed to realloc response response.\n"); 59 | } 60 | 61 | memcpy(response->data+response->len, ptr, size*nmemb); 62 | response->data[new_len] = '\0'; 63 | response->len = new_len; 64 | 65 | return size*nmemb; 66 | } 67 | 68 | int glms_fptr_fetch(GLMSEval *eval, GLMSAST *ast, GLMSASTBuffer *args, 69 | GLMSStack *stack, GLMSAST *out) { 70 | 71 | 72 | if (!glms_eval_expect(eval, stack, (GLMSASTType[]){ GLMS_AST_TYPE_STRING }, 1, args)) return 0; 73 | CURL *curl; 74 | CURLcode res; 75 | 76 | curl = curl_easy_init(); 77 | 78 | if (!curl) GLMS_WARNING_RETURN(0, stderr, "Failed to initialize curl.\n"); 79 | 80 | const char* path = glms_ast_get_string_value(&args->items[0]); 81 | 82 | GLMSFetchResponse* response = NEW(GLMSFetchResponse); 83 | 84 | curl_easy_setopt(curl, CURLOPT_URL, path); 85 | curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefunc); 86 | curl_easy_setopt(curl, CURLOPT_WRITEDATA, response); 87 | curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); 88 | curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, ""); 89 | res = curl_easy_perform(curl); 90 | 91 | long http_code = 0; 92 | curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code); 93 | response->code = http_code; 94 | curl_easy_cleanup(curl); 95 | 96 | 97 | GLMSAST* new_ast = glms_env_new_ast(eval->env, GLMS_AST_TYPE_STRUCT, true); 98 | new_ast->ptr = response; 99 | 100 | *out = (GLMSAST){ .type = GLMS_AST_TYPE_STACK_PTR, .as.stackptr.ptr = new_ast }; 101 | 102 | return 1; 103 | } 104 | 105 | int glms_response_fptr_text(GLMSEval *eval, GLMSAST *ast, GLMSASTBuffer *args, 106 | GLMSStack *stack, GLMSAST *out) { 107 | if (!ast->ptr) GLMS_WARNING_RETURN(0, stderr, "ptr == null.\n"); 108 | 109 | 110 | GLMSFetchResponse* response = (GLMSFetchResponse*)ast->ptr; 111 | 112 | 113 | GLMSAST* string_ast = glms_env_new_ast_string(eval->env, response->data, true); 114 | 115 | *out = (GLMSAST){ .type = GLMS_AST_TYPE_STACK_PTR, .as.stackptr.ptr = string_ast }; 116 | 117 | return 1; 118 | } 119 | 120 | int glms_response_fptr_json(GLMSEval *eval, GLMSAST *ast, GLMSASTBuffer *args, 121 | GLMSStack *stack, GLMSAST *out) { 122 | if (!ast->ptr) GLMS_WARNING_RETURN(0, stderr, "ptr == null.\n"); 123 | 124 | 125 | GLMSFetchResponse* response = (GLMSFetchResponse*)ast->ptr; 126 | 127 | const char* text = response->data; 128 | 129 | if (!text) GLMS_WARNING_RETURN(0, stderr, "cannot parse null.\n"); 130 | 131 | 132 | JSONOptions joptions = {0}; 133 | joptions.optimized_strings = true; 134 | JSON* j = json_parse(text, &joptions); 135 | 136 | if (!j) GLMS_WARNING_RETURN(0, stderr, "failed to parse json.\n"); 137 | 138 | GLMSAST* obj_ast = glms_ast_from_json(eval->env, j); 139 | 140 | *out = (GLMSAST){ .type = GLMS_AST_TYPE_STACK_PTR, .as.stackptr.ptr = obj_ast }; 141 | 142 | return 1; 143 | } 144 | 145 | int glms_response_fptr_status(GLMSEval *eval, GLMSAST *ast, GLMSASTBuffer *args, 146 | GLMSStack *stack, GLMSAST *out) { 147 | if (!ast->ptr) GLMS_WARNING_RETURN(0, stderr, "ptr == null.\n"); 148 | GLMSFetchResponse* response = (GLMSFetchResponse*)ast->ptr; 149 | 150 | 151 | GLMSAST* number_ast = glms_env_new_ast_number(eval->env, (float)response->code, true); 152 | 153 | *out = (GLMSAST){ .type = GLMS_AST_TYPE_STACK_PTR, .as.stackptr.ptr = number_ast }; 154 | 155 | return 1; 156 | } 157 | 158 | void glms_response_constructor(GLMSEval *eval, GLMSStack *stack, 159 | GLMSASTBuffer *args, GLMSAST *self) { 160 | 161 | self->constructor = glms_response_constructor; 162 | glms_ast_register_function(eval->env, self, "text", glms_response_fptr_text); 163 | glms_ast_register_function(eval->env, self, "json", glms_response_fptr_json); 164 | glms_ast_register_function(eval->env, self, "data", glms_response_fptr_json); 165 | glms_ast_register_function(eval->env, self, "status", glms_response_fptr_status); 166 | 167 | } 168 | 169 | void glms_fetch(GLMSEnv *env) { 170 | 171 | GLMSAST* t = glms_env_new_ast(env, GLMS_AST_TYPE_STRUCT, false); 172 | t->constructor = glms_response_constructor; 173 | glms_env_register_type(env, "response", t, glms_response_constructor, 0, glms_response_to_string, glms_response_destructor); 174 | 175 | glms_env_register_function(env, "fetch", glms_fptr_fetch); 176 | glms_env_register_function_signature(env, 0, "fetch", (GLMSFunctionSignature){ 177 | .return_type = (GLMSType){ .typename = "response" }, 178 | .args = (GLMSType[]) { 179 | (GLMSType){ GLMS_AST_TYPE_STRING, .valuename = "URL" } 180 | }, 181 | .args_length = 1 182 | }); 183 | } 184 | -------------------------------------------------------------------------------- /src/modules/file.c: -------------------------------------------------------------------------------- 1 | #include "glms/allocator.h" 2 | #include "glms/ast.h" 3 | #include "glms/ast_type.h" 4 | #include "glms/env.h" 5 | #include "glms/eval.h" 6 | #include "glms/iterator.h" 7 | #include "glms/macros.h" 8 | #include "glms/string_view.h" 9 | #include 10 | #include 11 | #include 12 | 13 | // typedef char* (*GLMSASTToString)(struct GLMS_AST_STRUCT *ast, GLMSAllocator alloc); 14 | 15 | 16 | int glms_file_fptr_open(GLMSEval *eval, GLMSAST *ast, GLMSASTBuffer *args, 17 | GLMSStack *stack, GLMSAST *out) { 18 | 19 | if (!glms_eval_expect(eval, stack, (GLMSASTType[]){ GLMS_AST_TYPE_STRING, GLMS_AST_TYPE_STRING }, 2, args)) return 0; 20 | 21 | 22 | 23 | const char* filepath = glms_string_view_get_value(&args->items[0].as.string.value); 24 | 25 | if (!glms_file_exists(filepath)) { 26 | const char* nextpath = glms_env_get_path_for(eval->env, filepath); 27 | if (nextpath != 0) filepath = nextpath; 28 | } 29 | 30 | 31 | const char* mode = glms_string_view_get_value(&args->items[1].as.string.value); 32 | 33 | FILE* fp = fopen(filepath, mode); 34 | 35 | if (!fp) { 36 | GLMS_WARNING(stderr, "Failed to open `%s`.\n", filepath); 37 | return 0; 38 | } 39 | 40 | GLMSAST* file_ast = glms_env_new_ast(eval->env, GLMS_AST_TYPE_STRUCT, true); 41 | 42 | GLMSFile* f = NEW(GLMSFile); 43 | f->fp = fp; 44 | f->open = true; 45 | file_ast->ptr = f; 46 | file_ast->constructor = glms_file_constructor; 47 | *out = (GLMSAST){ .type = GLMS_AST_TYPE_STACK_PTR, .as.stackptr.ptr = file_ast }; 48 | 49 | return 1; 50 | } 51 | 52 | int glms_file_fptr_close(GLMSEval *eval, GLMSAST *ast, GLMSASTBuffer *args, 53 | GLMSStack *stack, GLMSAST *out) { 54 | 55 | 56 | if (!ast->ptr) GLMS_WARNING_RETURN(0, stderr, "file handle not open.\n"); 57 | 58 | GLMSFile* f = (GLMSFile*)ast->ptr; 59 | 60 | if (!f->fp) GLMS_WARNING_RETURN(0, stderr, "file handle not open.\n"); 61 | 62 | FILE* fp = f->fp; 63 | fclose(fp); 64 | f->fp = 0; 65 | f->open = false; 66 | return 1; 67 | } 68 | 69 | int glms_file_fptr_write(GLMSEval *eval, GLMSAST *ast, GLMSASTBuffer *args, 70 | GLMSStack *stack, GLMSAST *out) { 71 | 72 | if (!glms_eval_expect(eval, stack, (GLMSASTType[]){ GLMS_AST_TYPE_STRING}, 1, args)) return 0; 73 | if (!ast->ptr) GLMS_WARNING_RETURN(0, stderr, "file handle not open.\n"); 74 | const char* buff = glms_string_view_get_value(&args->items[0].as.string.value); 75 | 76 | GLMSFile* f = (GLMSFile*)ast->ptr; 77 | if (!f->fp) GLMS_WARNING_RETURN(0, stderr, "file handle not open.\n"); 78 | 79 | FILE* fp = f->fp; 80 | 81 | fwrite(buff, sizeof(char), strlen(buff), fp); 82 | 83 | 84 | return 1; 85 | } 86 | 87 | 88 | int glms_file_iterator_next(GLMSEnv* env, GLMSAST *self, GLMSIterator *it, GLMSAST *out) { 89 | GLMSFileIteratorState* state = (GLMSFileIteratorState*)self->as.iterator.state; 90 | GLMSFile* f = state->file; 91 | 92 | 93 | char* line = state->line; 94 | 95 | 96 | size_t len = 0; 97 | ssize_t read = 0; 98 | 99 | 100 | 101 | if((read = getline(&line, &len, f->fp)) != -1) { 102 | state->read_bytes += read; 103 | GLMSAST* strast = glms_env_new_ast(env, GLMS_AST_TYPE_STRING, true); 104 | strast->as.string.heap = strdup(line); 105 | *out = (GLMSAST){ .type = GLMS_AST_TYPE_STACK_PTR, .as.stackptr.ptr = strast }; 106 | free(state->line); 107 | state->line = 0; 108 | } else { 109 | *out = (GLMSAST){ .type = GLMS_AST_TYPE_NULL }; 110 | 111 | if (state->line != 0) { 112 | free(state->line); 113 | state->line =0; 114 | } 115 | return 1; 116 | } 117 | 118 | return 1; 119 | } 120 | 121 | int glms_file_fptr_read_lines(GLMSEval *eval, GLMSAST *ast, GLMSASTBuffer *args, 122 | GLMSStack *stack, GLMSAST *out) { 123 | 124 | if (!ast->ptr) GLMS_WARNING_RETURN(0, stderr, "file handle not open.\n"); 125 | 126 | GLMSFile* f = (GLMSFile*)ast->ptr; 127 | if (!f->fp) GLMS_WARNING_RETURN(0, stderr, "file handle not open.\n"); 128 | 129 | 130 | GLMSAST* iter_ast = glms_env_new_ast(eval->env, GLMS_AST_TYPE_ITERATOR, true); 131 | iter_ast->as.iterator.it = (GLMSIterator){0}; 132 | iter_ast->iterator_next = glms_file_iterator_next; 133 | 134 | GLMSFileIteratorState* state = NEW(GLMSFileIteratorState); 135 | state->file = f; 136 | state->last_ptr = 0; 137 | state->line = 0; 138 | state->pos = 0; 139 | iter_ast->as.iterator.state = state; 140 | 141 | *out = (GLMSAST){ .type = GLMS_AST_TYPE_STACK_PTR, .as.stackptr.ptr = iter_ast }; 142 | return 1; 143 | } 144 | 145 | int glms_file_fptr_read(GLMSEval *eval, GLMSAST *ast, GLMSASTBuffer *args, 146 | GLMSStack *stack, GLMSAST *out) { 147 | 148 | if (!ast->ptr) GLMS_WARNING_RETURN(0, stderr, "file handle not open.\n"); 149 | 150 | GLMSFile* f = (GLMSFile*)ast->ptr; 151 | if (!f->fp) GLMS_WARNING_RETURN(0, stderr, "file handle not open.\n"); 152 | 153 | 154 | FILE* fp = f->fp; 155 | 156 | 157 | char *buffer = NULL; 158 | size_t len; 159 | ssize_t bytes_read = getdelim(&buffer, &len, '\0', fp); 160 | if (bytes_read == -1) { 161 | return 0; 162 | } 163 | 164 | 165 | GLMSAST* new_ast = glms_env_new_ast_string(eval->env, buffer, true); 166 | 167 | *out = (GLMSAST){ .type = GLMS_AST_TYPE_STACK_PTR, .as.stackptr.ptr = new_ast }; 168 | return 1; 169 | } 170 | 171 | void glms_file_constructor(GLMSEval *eval, GLMSStack *stack, 172 | GLMSASTBuffer *args, GLMSAST *self) { 173 | 174 | if (!self) return; 175 | self->type = GLMS_AST_TYPE_STRUCT; 176 | self->constructor = glms_file_constructor; 177 | //self->to_string = glms_file_to_string; 178 | glms_ast_register_function(eval->env, self, "open", glms_file_fptr_open); 179 | glms_ast_register_function(eval->env, self, "close", glms_file_fptr_close); 180 | glms_ast_register_function(eval->env, self, "write", glms_file_fptr_write); 181 | glms_ast_register_function(eval->env, self, "readLines", glms_file_fptr_read_lines); 182 | glms_ast_register_function(eval->env, self, "read", glms_file_fptr_read); 183 | 184 | glms_env_register_function_signature( 185 | eval->env, 186 | self, 187 | "readLines", 188 | (GLMSFunctionSignature){ 189 | .return_type = (GLMSType){ GLMS_AST_TYPE_ITERATOR }, 190 | .args_length = 0 191 | } 192 | ); 193 | 194 | glms_env_register_function_signature( 195 | eval->env, 196 | self, 197 | "open", 198 | (GLMSFunctionSignature){ 199 | .return_type = (GLMSType){ .typename = "file" }, 200 | .args = (GLMSType[]){ (GLMSType){ GLMS_AST_TYPE_STRING, .valuename = "filename" }, (GLMSType){ GLMS_AST_TYPE_STRING, .valuename = "mode" }}, 201 | .args_length = 2 202 | } 203 | ); 204 | 205 | glms_env_register_function_signature( 206 | eval->env, 207 | self, 208 | "close", 209 | (GLMSFunctionSignature){ 210 | .return_type = (GLMSType){ GLMS_AST_TYPE_BOOL }, 211 | .args_length = 0 212 | } 213 | ); 214 | 215 | glms_env_register_function_signature( 216 | eval->env, 217 | self, 218 | "write", 219 | (GLMSFunctionSignature){ 220 | .return_type = (GLMSType){ GLMS_AST_TYPE_BOOL }, 221 | .args = (GLMSType[]){ (GLMSType){ GLMS_AST_TYPE_STRING, .valuename = "text" }}, 222 | .args_length = 1 223 | } 224 | ); 225 | } 226 | 227 | void glms_file_type(GLMSEnv *env) { 228 | glms_env_register_type(env, "file", glms_env_new_ast(env, GLMS_AST_TYPE_STRUCT, false), glms_file_constructor, 0, 0/*glms_file_to_string*/, 0); 229 | } 230 | -------------------------------------------------------------------------------- /src/modules/image.c: -------------------------------------------------------------------------------- 1 | #include "glms/ast_type.h" 2 | #include "glms/builtin.h" 3 | #include "glms/macros.h" 4 | #include "glms/stack.h" 5 | #include "glms/string_view.h" 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | int glms_struct_image_fptr_get_pixel(GLMSEval *eval, GLMSAST *ast, 14 | GLMSASTBuffer *args, GLMSStack *stack, GLMSAST* out) { 15 | if (!args || args->length < 2) 16 | return 0; 17 | 18 | if (!ast->ptr) 19 | return 0; 20 | 21 | GIMG *gimg = (GIMG *)ast->ptr; 22 | 23 | int x = (int)(glms_eval(eval, args->items[0], stack)).as.number.value; 24 | int y = (int)(glms_eval(eval, args->items[1], stack)).as.number.value; 25 | 26 | Vector4 pixel = gimg_get_pixel_vec4(gimg, x, y); 27 | 28 | 29 | GLMSAST* new_ast = glms_env_new_ast(eval->env, GLMS_AST_TYPE_VEC4, true); 30 | new_ast->as.v4 = pixel; 31 | *out = (GLMSAST){ .type = GLMS_AST_TYPE_STACK_PTR, .as.stackptr.ptr = new_ast }; 32 | return 1; 33 | } 34 | 35 | int glms_struct_image_fptr_set_pixel(GLMSEval *eval, GLMSAST *ast, 36 | GLMSASTBuffer *args, GLMSStack *stack, GLMSAST* out) { 37 | if (!args || args->length < 3) 38 | return 0; 39 | 40 | if (!ast->ptr) 41 | return 0; 42 | 43 | GIMG *gimg = (GIMG *)ast->ptr; 44 | 45 | int x = (int)(glms_eval(eval, args->items[0], stack)).as.number.value; 46 | int y = (int)(glms_eval(eval, args->items[1], stack)).as.number.value; 47 | 48 | Vector4 pixel = glms_eval(eval, args->items[2], stack).as.v4; 49 | 50 | gimg_set_pixel_vec4(gimg, x, y, pixel); 51 | 52 | return 0; 53 | } 54 | 55 | int glms_struct_image_fptr_make(GLMSEval *eval, GLMSAST *ast, 56 | GLMSASTBuffer *args, GLMSStack *stack, GLMSAST* out) { 57 | if (!args || args->length < 2) 58 | GLMS_WARNING_RETURN(0, stderr, "not enough arguments.\n"); 59 | // if (ast->ptr) return 0; // already made 60 | 61 | GIMG *gimg = ast->ptr ? ast->ptr : NEW(GIMG); 62 | 63 | int w = (int)(glms_eval(eval, args->items[0], stack)).as.number.value; 64 | int h = (int)(glms_eval(eval, args->items[1], stack)).as.number.value; 65 | 66 | if (w <= 0 || h <= 0) GLMS_WARNING_RETURN(0, stderr, "Invalid dimensions for image.\n"); 67 | 68 | GLMSAST *imgast = glms_env_new_ast(eval->env, GLMS_AST_TYPE_STRUCT, true); 69 | if (!gimg_make(gimg, w, h, 4)) { 70 | GLMS_WARNING_RETURN(0, stderr, "Failed to create image.\n"); 71 | } 72 | 73 | imgast->ptr = gimg; 74 | 75 | *out = (GLMSAST){ .type = GLMS_AST_TYPE_STACK_PTR, .as.stackptr.ptr = imgast }; 76 | 77 | return 1; 78 | } 79 | 80 | int glms_struct_image_fptr_save(GLMSEval *eval, GLMSAST *ast, 81 | GLMSASTBuffer *args, GLMSStack *stack, GLMSAST* out) { 82 | if (!args || args->length <= 0) 83 | return 0; 84 | if (!ast->ptr) 85 | GLMS_WARNING_RETURN(0, stderr, "Image not initialized (ptr = null).\n"); 86 | 87 | GIMG *gimg = (GIMG *)ast->ptr; 88 | 89 | GLMSAST arg0 = glms_eval(eval, args->items[0], stack); 90 | 91 | int ok = 0; 92 | 93 | if (arg0.type == GLMS_AST_TYPE_STRING) { 94 | const char *strval = glms_string_view_get_value(&arg0.as.string.value); 95 | 96 | if (strval) { 97 | ok = gimg_save(*gimg, strval, true); 98 | } 99 | } 100 | 101 | *out = (GLMSAST){ .type = GLMS_AST_TYPE_BOOL, .as.boolean = ok ? true : false }; 102 | 103 | return 1; 104 | } 105 | 106 | 107 | int glms_struct_image_fptr_load(GLMSEval *eval, GLMSAST *ast, 108 | GLMSASTBuffer *args, GLMSStack *stack, GLMSAST* out) { 109 | if (!args || args->length <= 0) 110 | return 0; 111 | 112 | 113 | GIMG* gimg = NEW(GIMG); 114 | if (args != 0 && args->length > 0) { 115 | ast->ptr = ast->ptr ? ast->ptr : NEW(GIMG); 116 | GLMSAST arg0 = glms_eval(eval, args->items[0], stack); 117 | 118 | if (arg0.type == GLMS_AST_TYPE_STRING) { 119 | gimg_read_from_path(gimg, glms_string_view_get_value(&arg0.as.string.value)); 120 | } 121 | } 122 | 123 | GLMSAST* new_ast = glms_env_new_ast(eval->env, GLMS_AST_TYPE_STRUCT, true); 124 | new_ast->ptr = gimg; 125 | new_ast->constructor = glms_struct_image_constructor; 126 | glms_struct_image_constructor(eval, stack, 0, new_ast); 127 | 128 | *out = (GLMSAST){ .type = GLMS_AST_TYPE_STACK_PTR, .as.stackptr.ptr = new_ast }; 129 | 130 | return 1; 131 | } 132 | 133 | 134 | int glms_struct_image_fptr_shade(GLMSEval *eval, GLMSAST *ast, 135 | GLMSASTBuffer *args, GLMSStack *stack, GLMSAST* out) { 136 | 137 | if (!args || args->length <= 0) 138 | return 0; 139 | if (!ast->ptr) 140 | GLMS_WARNING_RETURN(0, stderr, "Image not initialized (ptr = null).\n"); 141 | 142 | GIMG *gimg = (GIMG *)ast->ptr; 143 | 144 | GLMSAST arg0 = args->items[0]; 145 | 146 | const char *signature[] = {"uv", "fragCoord", "resolution"}; 147 | 148 | GLMSAST *uv_ast = glms_env_new_ast_vec3(eval->env, VEC31(0), false); 149 | GLMSAST *coord_ast = glms_env_new_ast_vec3(eval->env, VEC31(0), false); 150 | GLMSAST *res_ast = glms_env_new_ast_vec3( 151 | eval->env, VEC3(gimg->width, gimg->height, 0), false); 152 | 153 | GLMSAST *signature_values[] = {uv_ast, coord_ast, res_ast}; 154 | 155 | GLMSAST call_ast = (GLMSAST){ .type = GLMS_AST_TYPE_CALL };//glms_env_new_ast(eval->env, GLMS_AST_TYPE_CALL, false); 156 | call_ast.as.call.func = &arg0; 157 | 158 | //GLMSStack tmp_stack = {0}; 159 | // glms_stack_init(&tmp_stack); 160 | // glms_stack_copy(*stack, &tmp_stack); 161 | 162 | for (int j = 0; j < 3; j++) { 163 | glms_stack_push(stack, signature[j], signature_values[j]); 164 | } 165 | 166 | for (int x = 0; x < gimg->width; x++) { 167 | for (int y = 0; y < gimg->height; y++) { 168 | float u = (float)x / (float)gimg->width; 169 | float v = (float)y / (float)gimg->height; 170 | uv_ast->as.v3 = VEC3(u, v, 0); 171 | coord_ast->as.v3 = VEC3(x, y, 0); 172 | 173 | GLMSAST result = glms_eval(eval, call_ast, stack); 174 | 175 | result = glms_eval(eval, result, stack); 176 | 177 | 178 | if (result.type == GLMS_AST_TYPE_VEC4) { 179 | Vector4 translated = result.as.v4; 180 | translated.x *= 255.0f; 181 | translated.y *= 255.0f; 182 | translated.z *= 255.0f; 183 | translated.w *= 255.0f; 184 | if (!gimg_set_pixel_vec4(gimg, x, y, translated)) { 185 | goto done; 186 | } 187 | } 188 | } 189 | } 190 | 191 | done: 192 | 193 | // glms_stack_clear_trash(&tmp_stack); 194 | //glms_stack_clear(&tmp_stack); 195 | 196 | return 1; 197 | } 198 | 199 | void glms_struct_image_constructor(GLMSEval *eval, GLMSStack *stack, 200 | GLMSASTBuffer *args, GLMSAST *self) { 201 | if (!self) return; 202 | GLMSAST *ast = self; 203 | ast->value_type = ast; 204 | ast->constructor = glms_struct_image_constructor; 205 | 206 | 207 | glms_ast_register_function(eval->env, ast, "getPixel", 208 | glms_struct_image_fptr_get_pixel); 209 | glms_ast_register_function(eval->env, ast, "setPixel", 210 | glms_struct_image_fptr_set_pixel); 211 | 212 | glms_ast_register_function(eval->env, ast, "load", 213 | glms_struct_image_fptr_load); 214 | 215 | glms_ast_register_function(eval->env, ast, "make", 216 | glms_struct_image_fptr_make); 217 | glms_ast_register_function(eval->env, ast, "save", 218 | glms_struct_image_fptr_save); 219 | glms_ast_register_function(eval->env, ast, "shade", 220 | glms_struct_image_fptr_shade); 221 | 222 | glms_env_register_function_signature( 223 | eval->env, 224 | ast, 225 | "load", 226 | (GLMSFunctionSignature){ 227 | .return_type = (GLMSType){GLMS_AST_TYPE_STRUCT}, 228 | .args = (GLMSType[]){ (GLMSType){ GLMS_AST_TYPE_STRING } }, 229 | .args_length = 1 230 | } 231 | ); 232 | 233 | glms_env_register_function_signature( 234 | eval->env, 235 | ast, 236 | "shade", 237 | (GLMSFunctionSignature){ 238 | .return_type = (GLMSType){GLMS_AST_TYPE_BOOL}, 239 | .args = (GLMSType[]){ (GLMSType){ GLMS_AST_TYPE_FUNC } }, 240 | .args_length = 1 241 | } 242 | ); 243 | 244 | glms_env_register_function_signature( 245 | eval->env, 246 | ast, 247 | "make", 248 | (GLMSFunctionSignature){ 249 | .return_type = (GLMSType){.typename = "image"}, 250 | .args = (GLMSType[]){ (GLMSType){ GLMS_AST_TYPE_NUMBER, .valuename = "width" }, (GLMSType){ GLMS_AST_TYPE_NUMBER, .valuename = "height" } }, 251 | .args_length = 2 252 | } 253 | ); 254 | 255 | glms_env_register_function_signature( 256 | eval->env, 257 | ast, 258 | "setPixel", 259 | (GLMSFunctionSignature){ 260 | .return_type = (GLMSType){ GLMS_AST_TYPE_VOID }, 261 | .args = (GLMSType[]){ (GLMSType){ GLMS_AST_TYPE_VEC4, .valuename = "pixel" }}, 262 | .args_length = 1 263 | } 264 | ); 265 | 266 | glms_env_register_function_signature( 267 | eval->env, 268 | ast, 269 | "getPixel", 270 | (GLMSFunctionSignature){ 271 | .return_type = (GLMSType){ GLMS_AST_TYPE_VEC4 }, 272 | .args = (GLMSType[]){ (GLMSType){ GLMS_AST_TYPE_NUMBER, .valuename = "x" }, (GLMSType){ GLMS_AST_TYPE_NUMBER, .valuename = "y" } }, 273 | .args_length = 2 274 | } 275 | ); 276 | 277 | glms_env_register_function_signature( 278 | eval->env, 279 | ast, 280 | "save", 281 | (GLMSFunctionSignature){ 282 | .return_type = (GLMSType){ GLMS_AST_TYPE_BOOL }, 283 | .args = (GLMSType[]){ (GLMSType){ GLMS_AST_TYPE_STRING, .valuename = "filename" }}, 284 | .args_length = 1 285 | } 286 | ); 287 | } 288 | 289 | void glms_struct_image_destructor(GLMSAST *ast) { 290 | if (!ast) 291 | return; 292 | 293 | if (!ast->ptr) 294 | return; 295 | 296 | GIMG *gimg = (GIMG *)ast->ptr; 297 | 298 | gimg_free(gimg, true); 299 | 300 | ast->ptr = 0; 301 | } 302 | 303 | void glms_struct_image(GLMSEnv *env) { 304 | GLMSAST *ast = glms_env_new_ast(env, GLMS_AST_TYPE_STRUCT, false); 305 | ast->constructor = glms_struct_image_constructor; 306 | // ast->to_string = glms_struct_image_to_string; 307 | // ast->ptr = NEW(GIMG); 308 | 309 | glms_env_register_type(env, "image", ast, glms_struct_image_constructor, 0, 310 | 0, 311 | glms_struct_image_destructor); 312 | } 313 | -------------------------------------------------------------------------------- /src/modules/iterator.c: -------------------------------------------------------------------------------- 1 | #include "glms/allocator.h" 2 | #include "glms/ast.h" 3 | #include "glms/ast_type.h" 4 | #include "glms/env.h" 5 | #include "glms/eval.h" 6 | #include "glms/macros.h" 7 | #include 8 | 9 | // typedef char* (*GLMSASTToString)(struct GLMS_AST_STRUCT *ast, GLMSAllocator alloc); 10 | 11 | char *glms_iterator_to_string(GLMSAST *ast, GLMSAllocator alloc) { 12 | return 0; 13 | } 14 | 15 | int glms_iterator_fptr_next(GLMSEval *eval, GLMSAST *ast, GLMSASTBuffer *args, 16 | GLMSStack *stack, GLMSAST *out) { 17 | 18 | if (!ast->iterator_next) { 19 | GLMS_WARNING_RETURN(0, stderr, "iterator_next == null.\n"); 20 | } 21 | 22 | 23 | return glms_ast_iterate(eval->env, ast, &ast->as.iterator.it, out); 24 | } 25 | 26 | void glms_iterator_constructor(GLMSEval *eval, GLMSStack *stack, 27 | GLMSASTBuffer *args, GLMSAST *self) { 28 | 29 | if (!self) return; 30 | self->type = GLMS_AST_TYPE_ITERATOR; 31 | self->constructor = glms_iterator_constructor; 32 | // self->to_string = glms_iterator_to_string; 33 | glms_ast_register_function(eval->env, self, "next", glms_iterator_fptr_next); 34 | } 35 | 36 | void glms_iterator_type(GLMSEnv *env) { 37 | glms_env_register_type(env, "iterator", glms_env_new_ast(env, GLMS_AST_TYPE_ITERATOR, false), glms_iterator_constructor, 0, 0, 0); 38 | } 39 | -------------------------------------------------------------------------------- /src/modules/json.c: -------------------------------------------------------------------------------- 1 | #include "fastjson/options.h" 2 | #include "glms/ast.h" 3 | #include "glms/ast_type.h" 4 | #include "glms/env.h" 5 | #include "glms/eval.h" 6 | #include "glms/type.h" 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | int glms_json_fptr_parse(GLMSEval *eval, GLMSAST *ast, GLMSASTBuffer *args, 13 | GLMSStack *stack, GLMSAST *out) { 14 | 15 | 16 | if (!glms_eval_expect(eval, stack, (GLMSASTType[]){ GLMS_AST_TYPE_STRING }, 1, args)) return 0; 17 | JSONOptions options = {0}; 18 | options.optimized_strings = true; 19 | 20 | const char* contents = glms_ast_get_string_value(&args->items[0]); 21 | 22 | JSON* j = 0; 23 | if (!(j = json_parse(contents, &options))) GLMS_WARNING_RETURN(0, stderr, "Failed to parse json.\n"); 24 | 25 | 26 | GLMSAST* new_ast = glms_ast_from_json(eval->env, j); 27 | 28 | *out = (GLMSAST){ .type = GLMS_AST_TYPE_STACK_PTR, .as.stackptr.ptr = new_ast }; 29 | 30 | 31 | return 1; 32 | } 33 | 34 | int glms_json_fptr_stringify(GLMSEval *eval, GLMSAST *ast, GLMSASTBuffer *args, 35 | GLMSStack *stack, GLMSAST *out) { 36 | 37 | if (!glms_eval_expect(eval, stack, (GLMSASTType[]){ GLMS_AST_TYPE_OBJECT }, 1, args)) return 0; 38 | 39 | GLMSAST obj = args->items[0]; 40 | if (!obj.json) return 0; 41 | 42 | GLMSAST* new_ast = glms_env_new_ast_string(eval->env, json_stringify(obj.json), true); 43 | 44 | *out = (GLMSAST){ .type = GLMS_AST_TYPE_STACK_PTR, .as.stackptr.ptr = new_ast }; 45 | 46 | return 1; 47 | } 48 | 49 | void glms_json_constructor(GLMSEval *eval, GLMSStack *stack, 50 | GLMSASTBuffer *args, GLMSAST *self) { 51 | 52 | if (self->constructed) return; 53 | self->constructed = true; 54 | 55 | self->constructor = glms_json_constructor; 56 | glms_ast_register_function(eval->env, self, "parse", glms_json_fptr_parse); 57 | glms_ast_register_function(eval->env, self, "stringify", glms_json_fptr_stringify); 58 | 59 | glms_env_register_function_signature(eval->env, self, "parse", (GLMSFunctionSignature){ 60 | .return_type = (GLMSType){ GLMS_AST_TYPE_OBJECT }, 61 | .args = (GLMSType[]) { 62 | (GLMSType){ GLMS_AST_TYPE_STRING, .valuename = "jsonString" } 63 | }, 64 | .args_length = 1 65 | }); 66 | 67 | glms_env_register_function_signature(eval->env, self, "stringify", (GLMSFunctionSignature){ 68 | .return_type = (GLMSType){ GLMS_AST_TYPE_STRING }, 69 | .args = (GLMSType[]) { 70 | (GLMSType){ GLMS_AST_TYPE_OBJECT } 71 | }, 72 | .args_length = 1 73 | }); 74 | } 75 | 76 | void glms_json(GLMSEnv *env) { 77 | 78 | GLMSAST* t = glms_env_new_ast(env, GLMS_AST_TYPE_STRUCT, false); 79 | t->constructor = glms_json_constructor; 80 | glms_env_register_type(env, "json", t, glms_json_constructor, 0, 0, 0); 81 | } 82 | -------------------------------------------------------------------------------- /src/modules/mat3.c: -------------------------------------------------------------------------------- 1 | #include "cglm/mat3.h" 2 | #include "cglm/cam.h" 3 | #include "cglm/struct/mat3.h" 4 | #include "cglm/struct/vec3.h" 5 | #include "cglm/types-struct.h" 6 | #include "glms/allocator.h" 7 | #include "glms/ast.h" 8 | #include "glms/ast_type.h" 9 | #include "glms/env.h" 10 | #include "glms/eval.h" 11 | #include "glms/token.h" 12 | #include 13 | #include 14 | 15 | // typedef char* (*GLMSASTToMat3)(struct GLMS_AST_STRUCT *ast, GLMSAllocator alloc); 16 | 17 | char *glms_mat3_to_string(GLMSAST *ast, GLMSAllocator alloc, GLMSEnv* env) { 18 | char* s = 0; 19 | 20 | alloc.strcat(alloc.user_ptr, &s, "{\n"); 21 | for (int i = 0; i < 3; i++) { 22 | for (int j = 0; j < 3; j++) { 23 | 24 | char tmp[16]; 25 | sprintf(tmp, "%1.6f", ast->as.m3.col[i].raw[j]); 26 | alloc.strcat(alloc.user_ptr, &s, tmp); 27 | 28 | if (j < 3-1) { 29 | alloc.strcat(alloc.user_ptr, &s, ", "); 30 | } 31 | } 32 | 33 | if (i < 3-1) { 34 | alloc.strcat(alloc.user_ptr, &s, "\n"); 35 | } 36 | } 37 | alloc.strcat(alloc.user_ptr, &s, "\n}"); 38 | 39 | return s; 40 | } 41 | 42 | int glms_mat3_type_op_overload_mul(GLMSEval *eval, GLMSStack *stack, 43 | GLMSAST *left, GLMSAST *right, 44 | GLMSAST *out) { 45 | 46 | 47 | if (left->type == GLMS_AST_TYPE_MAT3 && right->type == GLMS_AST_TYPE_MAT3) { 48 | *out = (GLMSAST){ .type = GLMS_AST_TYPE_MAT3, .as.m3 = glms_mat3_mul(left->as.m3, right->as.m3) }; 49 | return 1; 50 | } 51 | else if (left->type == GLMS_AST_TYPE_MAT3 && right->type == GLMS_AST_TYPE_VEC3) { 52 | Vector3 v = right->as.v3; 53 | vec3s r = glms_mat3_mulv(left->as.m3, (vec3s){ v.x, v.y, v.z }); 54 | *out = (GLMSAST){ .type = GLMS_AST_TYPE_VEC3, .as.v3 = VEC3(r.x, r.y, r.z) }; 55 | return 1; 56 | } else if (left->type == GLMS_AST_TYPE_MAT3 && right->type == GLMS_AST_TYPE_VEC3) { 57 | Vector3 v = right->as.v3; 58 | vec3s r = glms_mat3_mulv(left->as.m3, (vec3s){ v.x, v.y, v.z }); 59 | *out = (GLMSAST){ .type = GLMS_AST_TYPE_VEC3, .as.v3 = VEC3(r.x, r.y, r.z) }; 60 | return 1; 61 | } else if (right->type == GLMS_AST_TYPE_MAT3 && left->type == GLMS_AST_TYPE_VEC3) { 62 | Vector3 v = left->as.v3; 63 | vec3s r = glms_mat3_mulv(right->as.m3, (vec3s){ v.x, v.y, v.z }); 64 | *out = (GLMSAST){ .type = GLMS_AST_TYPE_VEC3, .as.v3 = VEC3(r.x, r.y, r.z) }; 65 | return 1; 66 | } else if (right->type == GLMS_AST_TYPE_MAT3 && left->type == GLMS_AST_TYPE_VEC3) { 67 | Vector3 v = left->as.v3; 68 | vec3s r = glms_mat3_mulv(right->as.m3, (vec3s){ v.x, v.y, v.z }); 69 | *out = (GLMSAST){ .type = GLMS_AST_TYPE_VEC3, .as.v3 = VEC3(r.x, r.y, r.z) }; 70 | return 1; 71 | } 72 | 73 | 74 | //glm_mat3_zero(result.as.m3); 75 | 76 | 77 | // glm_mat3_mul(left->as.m3, right->as.m3, out->as.m3); 78 | 79 | return 0; 80 | } 81 | 82 | void glms_mat3_constructor(GLMSEval *eval, GLMSStack *stack, 83 | GLMSASTBuffer *args, GLMSAST *self) { 84 | 85 | if (!self) return; 86 | self->type = GLMS_AST_TYPE_MAT3; 87 | self->constructor = glms_mat3_constructor; 88 | self->to_string = glms_mat3_to_string; 89 | 90 | glms_ast_register_operator_overload(eval->env, self, GLMS_TOKEN_TYPE_MUL, glms_mat3_type_op_overload_mul); 91 | } 92 | 93 | void glms_mat3_type(GLMSEnv *env) { 94 | GLMSAST* m3ast = glms_env_new_ast(env, GLMS_AST_TYPE_MAT3, false); 95 | m3ast->constructor = glms_mat3_constructor; 96 | glms_env_register_type(env, "mat3", m3ast, glms_mat3_constructor, 0, glms_mat3_to_string, 0); 97 | glms_env_register_type(env, GLMS_AST_TYPE_STR[GLMS_AST_TYPE_MAT3], m3ast, glms_mat3_constructor, 0, glms_mat3_to_string, 0); 98 | } 99 | -------------------------------------------------------------------------------- /src/modules/mat4.c: -------------------------------------------------------------------------------- 1 | #include "cglm/mat4.h" 2 | #include "cglm/cam.h" 3 | #include "cglm/struct/mat4.h" 4 | #include "cglm/struct/vec4.h" 5 | #include "cglm/types-struct.h" 6 | #include "glms/allocator.h" 7 | #include "glms/ast.h" 8 | #include "glms/ast_type.h" 9 | #include "glms/env.h" 10 | #include "glms/eval.h" 11 | #include "glms/token.h" 12 | #include 13 | #include 14 | 15 | // typedef char* (*GLMSASTToMat4)(struct GLMS_AST_STRUCT *ast, GLMSAllocator alloc); 16 | 17 | char *glms_mat4_to_string(GLMSAST *ast, GLMSAllocator alloc, GLMSEnv* env) { 18 | char* s = 0; 19 | 20 | alloc.strcat(alloc.user_ptr, &s, "{\n"); 21 | for (int i = 0; i < 4; i++) { 22 | for (int j = 0; j < 4; j++) { 23 | 24 | char tmp[16]; 25 | sprintf(tmp, "%1.6f", ast->as.m4.col[i].raw[j]); 26 | alloc.strcat(alloc.user_ptr, &s, tmp); 27 | 28 | if (j < 4-1) { 29 | alloc.strcat(alloc.user_ptr, &s, ", "); 30 | } 31 | } 32 | 33 | if (i < 4-1) { 34 | alloc.strcat(alloc.user_ptr, &s, "\n"); 35 | } 36 | } 37 | alloc.strcat(alloc.user_ptr, &s, "\n}"); 38 | 39 | return s; 40 | } 41 | 42 | int glms_mat4_type_op_overload_mul(GLMSEval *eval, GLMSStack *stack, 43 | GLMSAST *left, GLMSAST *right, 44 | GLMSAST *out) { 45 | 46 | 47 | if (left->type == GLMS_AST_TYPE_MAT4 && right->type == GLMS_AST_TYPE_MAT4) { 48 | *out = (GLMSAST){ .type = GLMS_AST_TYPE_MAT4, .as.m4 = glms_mat4_mul(left->as.m4, right->as.m4) }; 49 | return 1; 50 | } 51 | else if (left->type == GLMS_AST_TYPE_MAT4 && right->type == GLMS_AST_TYPE_VEC4) { 52 | Vector4 v = right->as.v4; 53 | vec4s r = glms_mat4_mulv(left->as.m4, (vec4s){ v.x, v.y, v.z, v.w }); 54 | *out = (GLMSAST){ .type = GLMS_AST_TYPE_VEC4, .as.v4 = VEC4(r.x, r.y, r.z, r.w) }; 55 | return 1; 56 | } else if (left->type == GLMS_AST_TYPE_MAT4 && right->type == GLMS_AST_TYPE_VEC3) { 57 | Vector3 v = right->as.v3; 58 | vec4s r = glms_mat4_mulv(left->as.m4, (vec4s){ v.x, v.y, v.z, 1.0f }); 59 | *out = (GLMSAST){ .type = GLMS_AST_TYPE_VEC4, .as.v4 = VEC4(r.x, r.y, r.z, r.w) }; 60 | return 1; 61 | } else if (right->type == GLMS_AST_TYPE_MAT4 && left->type == GLMS_AST_TYPE_VEC4) { 62 | Vector4 v = left->as.v4; 63 | vec4s r = glms_mat4_mulv(right->as.m4, (vec4s){ v.x, v.y, v.z, v.w }); 64 | *out = (GLMSAST){ .type = GLMS_AST_TYPE_VEC4, .as.v4 = VEC4(r.x, r.y, r.z, r.w) }; 65 | return 1; 66 | } else if (right->type == GLMS_AST_TYPE_MAT4 && left->type == GLMS_AST_TYPE_VEC3) { 67 | Vector3 v = left->as.v3; 68 | vec4s r = glms_mat4_mulv(right->as.m4, (vec4s){ v.x, v.y, v.z, 1.0f }); 69 | *out = (GLMSAST){ .type = GLMS_AST_TYPE_VEC4, .as.v4 = VEC4(r.x, r.y, r.z, r.w) }; 70 | return 1; 71 | } 72 | 73 | 74 | //glm_mat4_zero(result.as.m4); 75 | 76 | 77 | // glm_mat4_mul(left->as.m4, right->as.m4, out->as.m4); 78 | 79 | return 0; 80 | } 81 | 82 | void glms_mat4_constructor(GLMSEval *eval, GLMSStack *stack, 83 | GLMSASTBuffer *args, GLMSAST *self) { 84 | 85 | if (!self) return; 86 | self->type = GLMS_AST_TYPE_MAT4; 87 | self->constructor = glms_mat4_constructor; 88 | self->to_string = glms_mat4_to_string; 89 | 90 | glms_ast_register_operator_overload(eval->env, self, GLMS_TOKEN_TYPE_MUL, glms_mat4_type_op_overload_mul); 91 | } 92 | 93 | void glms_mat4_type(GLMSEnv *env) { 94 | GLMSAST* m4ast = glms_env_new_ast(env, GLMS_AST_TYPE_MAT4, false); 95 | m4ast->constructor = glms_mat4_constructor; 96 | glms_env_register_type(env, "mat4", m4ast, glms_mat4_constructor, 0, glms_mat4_to_string, 0); 97 | glms_env_register_type(env, GLMS_AST_TYPE_STR[GLMS_AST_TYPE_MAT4], m4ast, glms_mat4_constructor, 0, glms_mat4_to_string, 0); 98 | } 99 | -------------------------------------------------------------------------------- /src/modules/string.c: -------------------------------------------------------------------------------- 1 | #include "glms/allocator.h" 2 | #include "glms/ast.h" 3 | #include "glms/ast_type.h" 4 | #include "glms/env.h" 5 | #include "glms/eval.h" 6 | #include "glms/string_view.h" 7 | #include "glms/token.h" 8 | #include 9 | #include 10 | 11 | // typedef char* (*GLMSASTToString)(struct GLMS_AST_STRUCT *ast, GLMSAllocator alloc); 12 | 13 | char *glms_string_to_string(GLMSAST *ast, GLMSAllocator alloc) { return 0; } 14 | 15 | int glms_string_type_op_overload_add(GLMSEval *eval, GLMSStack *stack, 16 | GLMSAST *left, GLMSAST *right, 17 | GLMSAST *out) { 18 | 19 | 20 | 21 | if (left->type != GLMS_AST_TYPE_STRING && right->type != GLMS_AST_TYPE_STRING) 22 | return 0; 23 | 24 | 25 | const char* left_value = glms_ast_get_string_value(left); 26 | const char* right_value = glms_ast_get_string_value(right); 27 | 28 | char* s = 0; 29 | if (left_value) { 30 | text_append(&s, left_value); 31 | } 32 | 33 | if (right_value) { 34 | text_append(&s, right_value); 35 | } 36 | 37 | GLMSAST* new_ast = glms_env_new_ast(eval->env, GLMS_AST_TYPE_STRING, true); 38 | new_ast->as.string.heap = s; 39 | 40 | *out = (GLMSAST){ .type = GLMS_AST_TYPE_STACK_PTR, .as.stackptr.ptr = new_ast }; 41 | return 1; 42 | } 43 | 44 | int glms_string_fptr_replace(GLMSEval *eval, GLMSAST *ast, GLMSASTBuffer *args, 45 | GLMSStack *stack, GLMSAST *out) { 46 | 47 | if (!glms_eval_expect(eval, stack, (GLMSASTType[]){ GLMS_AST_TYPE_STRING, GLMS_AST_TYPE_STRING }, 2, args)) return 0; 48 | 49 | const char* needle = glms_ast_get_string_value(&args->items[0]); 50 | const char* repl = glms_ast_get_string_value(&args->items[1]); 51 | const char* value = glms_ast_get_string_value(ast); 52 | char* new_str = text_replace(value, needle, repl); 53 | if (!new_str) return 0; 54 | 55 | 56 | GLMSAST* new_ast = glms_env_new_ast(eval->env, GLMS_AST_TYPE_STRING, true); 57 | new_ast->as.string.heap = new_str; 58 | 59 | 60 | *out = (GLMSAST){ .type = GLMS_AST_TYPE_STACK_PTR, .as.stackptr.ptr = new_ast }; 61 | 62 | return 1; 63 | } 64 | 65 | int glms_string_fptr_includes(GLMSEval *eval, GLMSAST *ast, GLMSASTBuffer *args, 66 | GLMSStack *stack, GLMSAST *out) { 67 | 68 | if (!glms_eval_expect(eval, stack, (GLMSASTType[]){ GLMS_AST_TYPE_STRING }, 1, args)) return 0; 69 | 70 | const char* needle = glms_ast_get_string_value(&args->items[0]); 71 | const char* value = glms_ast_get_string_value(ast); 72 | 73 | 74 | if (!needle || !value) { 75 | 76 | *out = (GLMSAST){ .type = GLMS_AST_TYPE_BOOL, .as.boolean = false }; 77 | return 1; 78 | } 79 | 80 | *out = (GLMSAST){ .type = GLMS_AST_TYPE_BOOL, .as.boolean = (strstr(value, needle) != 0) }; 81 | 82 | return 1; 83 | } 84 | 85 | void glms_string_constructor(GLMSEval *eval, GLMSStack *stack, 86 | GLMSASTBuffer *args, GLMSAST *self) { 87 | 88 | if (!self) return; 89 | self->type = GLMS_AST_TYPE_STRING; 90 | self->constructor = glms_string_constructor; 91 | self->to_string = 0; 92 | 93 | glms_ast_register_operator_overload(eval->env, self, GLMS_TOKEN_TYPE_ADD, glms_string_type_op_overload_add); 94 | glms_ast_register_function(eval->env, self, "replace", glms_string_fptr_replace); 95 | glms_ast_register_function(eval->env, self, "includes", glms_string_fptr_includes); 96 | 97 | glms_env_register_function_signature( 98 | eval->env, 99 | self, 100 | "replace", 101 | (GLMSFunctionSignature){ 102 | .return_type = (GLMSType){ GLMS_AST_TYPE_STRING }, 103 | .args = (GLMSType[]){ (GLMSType){ GLMS_AST_TYPE_STRING, .valuename = "pattern" }, (GLMSType){ GLMS_AST_TYPE_STRING, .valuename = "replacement" }}, 104 | .args_length = 2 105 | } 106 | ); 107 | 108 | glms_env_register_function_signature( 109 | eval->env, 110 | self, 111 | "includes", 112 | (GLMSFunctionSignature){ 113 | .return_type = (GLMSType){ GLMS_AST_TYPE_BOOL }, 114 | .args = (GLMSType[]){ (GLMSType){ GLMS_AST_TYPE_STRING, .valuename = "needle" }}, 115 | .args_length = 1 116 | } 117 | ); 118 | } 119 | 120 | void glms_string_type(GLMSEnv *env) { 121 | glms_env_register_type(env, "string", glms_env_new_ast(env, GLMS_AST_TYPE_STRING, false), glms_string_constructor, 0, 0, 0); 122 | glms_env_register_type(env, GLMS_AST_TYPE_STR[GLMS_AST_TYPE_STRING], glms_env_new_ast(env, GLMS_AST_TYPE_STRING, false), glms_string_constructor, 0, 0, 0); 123 | } 124 | -------------------------------------------------------------------------------- /src/modules/vec2.c: -------------------------------------------------------------------------------- 1 | #include "glms/ast.h" 2 | #include 3 | #include 4 | #include 5 | 6 | 7 | int glms_struct_vec2_swizzle(GLMSEval *eval, GLMSStack *stack, GLMSAST *ast, 8 | GLMSAST *accessor, GLMSAST *out) { 9 | 10 | const char *id = glms_ast_get_string_value(accessor); 11 | if (!id) 12 | return 0; 13 | 14 | int idx = 0; 15 | Vector2 v2 = ast->as.v2; 16 | 17 | if (strlen(id) > 1) { 18 | if (strcmp(id, "xy") == 0) { 19 | *out = (GLMSAST){.type = GLMS_AST_TYPE_VEC2, .as.v2 = v2}; 20 | return 1; 21 | } else if (strcmp(id, "yx")) { 22 | *out = (GLMSAST){.type = GLMS_AST_TYPE_VEC2, .as.v2 = VEC2(v2.y, v2.x)}; 23 | return 1; 24 | } else { 25 | GLMS_WARNING_RETURN(0, stderr, "Unsupported swizzle %s\n", id); 26 | } 27 | } else { 28 | 29 | idx = ((int)id[0]) - 120; 30 | 31 | switch (id[0]) { 32 | case 'x': idx = 0; break; 33 | case 'y': idx = 1; break; 34 | } 35 | } 36 | 37 | GLMS_WARNING_RETURN(0, stderr, "Invalid swizzle `%s`\n", id); 38 | *out = (GLMSAST){.type = GLMS_AST_TYPE_NUMBER, .as.number.value = idx == 0 ? v2.x : v2.y}; 39 | return 1; 40 | } 41 | 42 | int glms_struct_vec2_op_overload_mul(GLMSEval *eval, GLMSStack *stack, 43 | GLMSAST *left, GLMSAST *right, 44 | GLMSAST *out) { 45 | 46 | 47 | 48 | if (!glms_ast_is_vector(left) && !glms_ast_is_vector(right)) 49 | return 0; 50 | 51 | Vector2 v = VEC2(0, 0); 52 | 53 | 54 | if (left->type == GLMS_AST_TYPE_VEC2 && right->type == GLMS_AST_TYPE_NUMBER) { 55 | v = left->as.v2; 56 | v = vector2_scale(v, right->as.number.value); 57 | } else if (left->type == GLMS_AST_TYPE_NUMBER && 58 | right->type == GLMS_AST_TYPE_VEC2) { 59 | v = right->as.v2; 60 | v = vector2_scale(v, left->as.number.value); 61 | } else if (left->type == GLMS_AST_TYPE_VEC2 && 62 | right->type == GLMS_AST_TYPE_VEC2) { 63 | v = vector2_mul(left->as.v2, right->as.v2); 64 | } 65 | 66 | *out = (GLMSAST){.type = GLMS_AST_TYPE_VEC2, .as.v2 = v}; 67 | return 1; 68 | } 69 | 70 | int glms_struct_vec2_op_overload_add(GLMSEval *eval, GLMSStack *stack, 71 | GLMSAST *left, GLMSAST *right, 72 | GLMSAST *out) { 73 | 74 | 75 | 76 | if (!glms_ast_is_vector(left) && !glms_ast_is_vector(right)) 77 | return 0; 78 | 79 | Vector2 v = VEC2(0, 0); 80 | 81 | 82 | if (left->type == GLMS_AST_TYPE_VEC2 && right->type == GLMS_AST_TYPE_NUMBER) { 83 | v = left->as.v2; 84 | v.x += glms_ast_number(*right); 85 | v.y += glms_ast_number(*right); 86 | } else if (left->type == GLMS_AST_TYPE_NUMBER && 87 | right->type == GLMS_AST_TYPE_VEC2) { 88 | v = right->as.v2; 89 | v.x += glms_ast_number(*left); 90 | v.y += glms_ast_number(*left); 91 | } else if (left->type == GLMS_AST_TYPE_VEC2 && 92 | right->type == GLMS_AST_TYPE_VEC2) { 93 | v = vector2_add(left->as.v2, right->as.v2); 94 | } 95 | 96 | *out = (GLMSAST){.type = GLMS_AST_TYPE_VEC2, .as.v2 = v}; 97 | return 1; 98 | } 99 | 100 | int glms_struct_vec2_op_overload_div(GLMSEval *eval, GLMSStack *stack, 101 | GLMSAST *left, GLMSAST *right, 102 | GLMSAST *out) { 103 | 104 | if (!glms_ast_is_vector(left) && !glms_ast_is_vector(right)) 105 | return 0; 106 | 107 | Vector2 v = VEC2(0, 0); 108 | 109 | if (left->type == GLMS_AST_TYPE_VEC2 && right->type == GLMS_AST_TYPE_NUMBER) { 110 | v = left->as.v2; 111 | v = vector2_scale(v, 1.0f / right->as.number.value); 112 | } else if (left->type == GLMS_AST_TYPE_NUMBER && 113 | right->type == GLMS_AST_TYPE_VEC2) { 114 | v = right->as.v2; 115 | v = vector2_scale(v, 1.0f / left->as.number.value); 116 | } else if (left->type == GLMS_AST_TYPE_VEC2 && 117 | right->type == GLMS_AST_TYPE_VEC2) { 118 | v.x = left->as.v2.x / right->as.v2.x; 119 | v.y = left->as.v2.y / right->as.v2.y; 120 | } 121 | 122 | *out = (GLMSAST){.type = GLMS_AST_TYPE_VEC2, .as.v2 = v}; 123 | 124 | return 1; 125 | } 126 | 127 | int glms_struct_vec2_op_overload_sub(GLMSEval *eval, GLMSStack *stack, 128 | GLMSAST *left, GLMSAST *right, 129 | GLMSAST *out) { 130 | 131 | if (!glms_ast_is_vector(left) && !glms_ast_is_vector(right)) 132 | return 0; 133 | 134 | Vector2 v = VEC2(0, 0); 135 | 136 | if (left->type == GLMS_AST_TYPE_VEC2 && right->type == GLMS_AST_TYPE_NUMBER) { 137 | v = left->as.v2; 138 | float f = glms_ast_number(*right); 139 | v.x -= f; 140 | v.y -= f; 141 | } else if (left->type == GLMS_AST_TYPE_NUMBER && 142 | right->type == GLMS_AST_TYPE_VEC2) { 143 | float f = glms_ast_number(*left); 144 | v = right->as.v2; 145 | 146 | v.x -= f; 147 | v.y -= f; 148 | } else if (left->type == GLMS_AST_TYPE_VEC2 && 149 | right->type == GLMS_AST_TYPE_VEC2) { 150 | v = vector2_sub(left->as.v2, right->as.v2); 151 | } 152 | 153 | *out = (GLMSAST){.type = GLMS_AST_TYPE_VEC2, .as.v2 = v}; 154 | 155 | return 1; 156 | } 157 | 158 | 159 | char *glms_struct_vec2_to_string(GLMSAST *ast, GLMSAllocator alloc, GLMSEnv* env) { 160 | Vector2 v = ast->as.v2; 161 | 162 | char tmp[256]; 163 | sprintf(tmp, "VEC2(%1.6f, %1.6f)", v.x, v.y); 164 | 165 | return alloc.strdup(alloc.user_ptr, tmp); 166 | } 167 | 168 | void glms_struct_vec2_constructor(GLMSEval *eval, GLMSStack *stack, 169 | GLMSASTBuffer *args, GLMSAST *self) { 170 | 171 | if (!self) 172 | return; 173 | 174 | GLMSAST *ast = self; 175 | ast->type = GLMS_AST_TYPE_VEC2; 176 | ast->swizzle = glms_struct_vec2_swizzle; 177 | ast->constructor = glms_struct_vec2_constructor; 178 | ast->to_string = glms_struct_vec2_to_string; 179 | glms_ast_register_operator_overload(eval->env, ast, GLMS_TOKEN_TYPE_MUL, 180 | glms_struct_vec2_op_overload_mul); 181 | glms_ast_register_operator_overload(eval->env, ast, GLMS_TOKEN_TYPE_DIV, 182 | glms_struct_vec2_op_overload_div); 183 | glms_ast_register_operator_overload(eval->env, ast, GLMS_TOKEN_TYPE_SUB, 184 | glms_struct_vec2_op_overload_sub); 185 | 186 | glms_ast_register_operator_overload(eval->env, ast, GLMS_TOKEN_TYPE_ADD, 187 | glms_struct_vec2_op_overload_add); 188 | 189 | 190 | if (!args) 191 | return; 192 | 193 | if (args->length >= 2) { 194 | float x = (glms_eval(eval, args->items[0], stack)).as.number.value; 195 | float y = (glms_eval(eval, args->items[1], stack)).as.number.value; 196 | 197 | ast->as.v2 = VEC2(x, y); 198 | } else if (args->length == 1) { 199 | float x = (glms_eval(eval, args->items[0], stack)).as.number.value; 200 | ast->as.v2 = VEC2(x, x); 201 | } 202 | } 203 | 204 | void glms_struct_vec2(GLMSEnv *env) { 205 | GLMSAST* t = glms_env_new_ast(env, GLMS_AST_TYPE_VEC2, false); 206 | glms_env_register_type( 207 | env, "vec2", t, 208 | glms_struct_vec2_constructor, glms_struct_vec2_swizzle, 0, 0); 209 | 210 | glms_env_register_type( 211 | env, GLMS_AST_TYPE_STR[GLMS_AST_TYPE_VEC2], t, 212 | glms_struct_vec2_constructor, glms_struct_vec2_swizzle, 0, 0); 213 | // glms_env_register_struct(env, "vec2", (GLMSAST*[]){ 214 | // glms_env_new_ast_field(env, GLMS_TOKEN_TYPE_SPECIAL_NUMBER, "x"), 215 | // glms_env_new_ast_field(env, GLMS_TOKEN_TYPE_SPECIAL_NUMBER, "y"), 216 | // glms_env_new_ast_field(env, GLMS_TOKEN_TYPE_SPECIAL_NUMBER, "z") 217 | // }, 3); 218 | } 219 | -------------------------------------------------------------------------------- /src/modules/vec3.c: -------------------------------------------------------------------------------- 1 | #include "glms/ast.h" 2 | #include 3 | #include 4 | #include 5 | 6 | 7 | int glms_struct_vec3_swizzle(GLMSEval *eval, GLMSStack *stack, GLMSAST *ast, 8 | GLMSAST *accessor, GLMSAST *out) { 9 | 10 | const char *id = glms_ast_get_string_value(accessor); 11 | if (!id) 12 | return 0; 13 | 14 | int idx = 0; 15 | Vector3 v3 = ast->as.v3; 16 | 17 | if (strlen(id) > 1) { 18 | if (strcmp(id, "xyz") == 0) { 19 | *out = (GLMSAST){.type = GLMS_AST_TYPE_VEC3, .as.v3 = v3}; 20 | return 1; 21 | } else { 22 | GLMS_WARNING_RETURN(0, stderr, "Unsupported swizzle %s\n", id); 23 | } 24 | } else { 25 | 26 | idx = ((int)id[0]) - 120; 27 | 28 | switch (id[0]) { 29 | case 'r': idx = 0; break; 30 | case 'g': idx = 1; break; 31 | case 'b': idx = 2; break; 32 | default: {}; break; 33 | } 34 | } 35 | 36 | if (idx < 0 || idx >= 3) { 37 | GLMS_WARNING_RETURN(0, stderr, "Invalid swizzle `%s`\n", id); 38 | } 39 | 40 | float v = vector3_get_component(ast->as.v3, idx); 41 | 42 | *out = (GLMSAST){.type = GLMS_AST_TYPE_NUMBER, .as.number.value = v}; 43 | return 1; 44 | } 45 | 46 | int glms_struct_vec3_op_overload_mul(GLMSEval *eval, GLMSStack *stack, 47 | GLMSAST *left, GLMSAST *right, 48 | GLMSAST *out) { 49 | 50 | 51 | 52 | if (!glms_ast_is_vector(left) && !glms_ast_is_vector(right)) 53 | return 0; 54 | 55 | Vector3 v = VEC31(0); 56 | 57 | 58 | if (left->type == GLMS_AST_TYPE_VEC3 && right->type == GLMS_AST_TYPE_NUMBER) { 59 | v = left->as.v3; 60 | v = vector3_scale(v, right->as.number.value); 61 | } else if (left->type == GLMS_AST_TYPE_NUMBER && 62 | right->type == GLMS_AST_TYPE_VEC3) { 63 | v = right->as.v3; 64 | v = vector3_scale(v, left->as.number.value); 65 | } else if (left->type == GLMS_AST_TYPE_VEC3 && 66 | right->type == GLMS_AST_TYPE_VEC3) { 67 | v = vector3_mul(left->as.v3, right->as.v3); 68 | } 69 | 70 | *out = (GLMSAST){.type = GLMS_AST_TYPE_VEC3, .as.v3 = v}; 71 | return 1; 72 | } 73 | 74 | int glms_struct_vec3_op_overload_add(GLMSEval *eval, GLMSStack *stack, 75 | GLMSAST *left, GLMSAST *right, 76 | GLMSAST *out) { 77 | 78 | 79 | 80 | if (!glms_ast_is_vector(left) && !glms_ast_is_vector(right)) 81 | return 0; 82 | 83 | Vector3 v = VEC31(0); 84 | 85 | 86 | if (left->type == GLMS_AST_TYPE_VEC3 && right->type == GLMS_AST_TYPE_NUMBER) { 87 | v = left->as.v3; 88 | v.x += glms_ast_number(*right); 89 | v.y += glms_ast_number(*right); 90 | v.z += glms_ast_number(*right); 91 | } else if (left->type == GLMS_AST_TYPE_NUMBER && 92 | right->type == GLMS_AST_TYPE_VEC3) { 93 | v = right->as.v3; 94 | v.x += glms_ast_number(*left); 95 | v.y += glms_ast_number(*left); 96 | v.z += glms_ast_number(*left); 97 | } else if (left->type == GLMS_AST_TYPE_VEC3 && 98 | right->type == GLMS_AST_TYPE_VEC3) { 99 | v = vector3_add(left->as.v3, right->as.v3); 100 | } 101 | 102 | *out = (GLMSAST){.type = GLMS_AST_TYPE_VEC3, .as.v3 = v}; 103 | return 1; 104 | } 105 | 106 | int glms_struct_vec3_op_overload_div(GLMSEval *eval, GLMSStack *stack, 107 | GLMSAST *left, GLMSAST *right, 108 | GLMSAST *out) { 109 | 110 | if (!glms_ast_is_vector(left) && !glms_ast_is_vector(right)) 111 | return 0; 112 | 113 | Vector3 v = VEC31(0); 114 | 115 | if (left->type == GLMS_AST_TYPE_VEC3 && right->type == GLMS_AST_TYPE_NUMBER) { 116 | v = left->as.v3; 117 | v = vector3_scale(v, 1.0f / right->as.number.value); 118 | } else if (left->type == GLMS_AST_TYPE_NUMBER && 119 | right->type == GLMS_AST_TYPE_VEC3) { 120 | v = right->as.v3; 121 | v = vector3_scale(v, 1.0f / left->as.number.value); 122 | } else if (left->type == GLMS_AST_TYPE_VEC3 && 123 | right->type == GLMS_AST_TYPE_VEC3) { 124 | v.x = left->as.v3.x / right->as.v3.x; 125 | v.y = left->as.v3.y / right->as.v3.y; 126 | v.z = left->as.v3.z / right->as.v3.z; 127 | } 128 | 129 | *out = (GLMSAST){.type = GLMS_AST_TYPE_VEC3, .as.v3 = v}; 130 | 131 | return 1; 132 | } 133 | 134 | int glms_struct_vec3_op_overload_sub(GLMSEval *eval, GLMSStack *stack, 135 | GLMSAST *left, GLMSAST *right, 136 | GLMSAST *out) { 137 | 138 | if (!glms_ast_is_vector(left) && !glms_ast_is_vector(right)) 139 | return 0; 140 | 141 | Vector3 v = VEC31(0); 142 | 143 | if (left->type == GLMS_AST_TYPE_VEC3 && right->type == GLMS_AST_TYPE_NUMBER) { 144 | v = left->as.v3; 145 | float f = glms_ast_number(*right); 146 | v.x -= f; 147 | v.y -= f; 148 | v.z -= f; 149 | } else if (left->type == GLMS_AST_TYPE_NUMBER && 150 | right->type == GLMS_AST_TYPE_VEC3) { 151 | float f = glms_ast_number(*left); 152 | v = right->as.v3; 153 | 154 | v.x -= f; 155 | v.y -= f; 156 | v.z -= f; 157 | } else if (left->type == GLMS_AST_TYPE_VEC3 && 158 | right->type == GLMS_AST_TYPE_VEC3) { 159 | v = vector3_sub(left->as.v3, right->as.v3); 160 | } 161 | 162 | *out = (GLMSAST){.type = GLMS_AST_TYPE_VEC3, .as.v3 = v}; 163 | 164 | return 1; 165 | } 166 | 167 | int glms_struct_vec3_func_overload_mix(struct GLMS_EVAL_STRUCT* eval, struct GLMS_AST_STRUCT* ast, struct GLMS_BUFFER_GLMSAST* args, struct GLMS_STACK_STRUCT* stack, struct GLMS_AST_STRUCT* out) { 168 | 169 | 170 | if (!glms_eval_expect(eval, stack, (GLMSASTType[]){ GLMS_AST_TYPE_VEC3, GLMS_AST_TYPE_VEC3, GLMS_AST_TYPE_NUMBER }, 3, args)) return 0; 171 | 172 | 173 | Vector3 v1 = args->items[0].as.v3; 174 | Vector3 v2 = args->items[1].as.v3; 175 | float scale = glms_ast_number(args->items[2]); 176 | 177 | Vector3 v = vector3_lerp(v1, v2, scale); 178 | 179 | *out = (GLMSAST){ .type = GLMS_AST_TYPE_VEC3, .as.v3 = v}; 180 | 181 | return 1; 182 | } 183 | 184 | char *glms_struct_vec3_to_string(GLMSAST *ast, GLMSAllocator alloc, GLMSEnv* env) { 185 | Vector3 v = ast->as.v3; 186 | 187 | char tmp[256]; 188 | sprintf(tmp, "VEC3(%1.6f, %1.6f, %1.6f)", v.x, v.y, v.z); 189 | 190 | return alloc.strdup(alloc.user_ptr, tmp); 191 | } 192 | 193 | void glms_struct_vec3_constructor(GLMSEval *eval, GLMSStack *stack, 194 | GLMSASTBuffer *args, GLMSAST *self) { 195 | 196 | if (!self) 197 | return; 198 | 199 | GLMSAST *ast = self; 200 | ast->type = GLMS_AST_TYPE_VEC3; 201 | ast->swizzle = glms_struct_vec3_swizzle; 202 | ast->constructor = glms_struct_vec3_constructor; 203 | ast->to_string = glms_struct_vec3_to_string; 204 | glms_ast_register_operator_overload(eval->env, ast, GLMS_TOKEN_TYPE_MUL, 205 | glms_struct_vec3_op_overload_mul); 206 | glms_ast_register_operator_overload(eval->env, ast, GLMS_TOKEN_TYPE_DIV, 207 | glms_struct_vec3_op_overload_div); 208 | glms_ast_register_operator_overload(eval->env, ast, GLMS_TOKEN_TYPE_SUB, 209 | glms_struct_vec3_op_overload_sub); 210 | 211 | glms_ast_register_operator_overload(eval->env, ast, GLMS_TOKEN_TYPE_ADD, 212 | glms_struct_vec3_op_overload_add); 213 | 214 | glms_ast_register_func_overload(eval->env, ast, "mix", glms_struct_vec3_func_overload_mix); 215 | glms_ast_register_func_overload(eval->env, ast, "lerp", glms_struct_vec3_func_overload_mix); 216 | 217 | if (!args) 218 | return; 219 | 220 | if (args->length >= 3) { 221 | float x = (glms_eval(eval, args->items[0], stack)).as.number.value; 222 | float y = (glms_eval(eval, args->items[1], stack)).as.number.value; 223 | float z = (glms_eval(eval, args->items[2], stack)).as.number.value; 224 | 225 | ast->as.v3 = VEC3(x, y, z); 226 | } else if (args->length == 1) { 227 | float x = (glms_eval(eval, args->items[0], stack)).as.number.value; 228 | ast->as.v3 = VEC31(x); 229 | } 230 | } 231 | 232 | void glms_struct_vec3(GLMSEnv *env) { 233 | GLMSAST* t = glms_env_new_ast(env, GLMS_AST_TYPE_VEC3, false); 234 | glms_env_register_type( 235 | env, "vec3", t, 236 | glms_struct_vec3_constructor, glms_struct_vec3_swizzle, 0, 0); 237 | 238 | glms_env_register_type( 239 | env, GLMS_AST_TYPE_STR[GLMS_AST_TYPE_VEC3], t, 240 | glms_struct_vec3_constructor, glms_struct_vec3_swizzle, 0, 0); 241 | // glms_env_register_struct(env, "vec3", (GLMSAST*[]){ 242 | // glms_env_new_ast_field(env, GLMS_TOKEN_TYPE_SPECIAL_NUMBER, "x"), 243 | // glms_env_new_ast_field(env, GLMS_TOKEN_TYPE_SPECIAL_NUMBER, "y"), 244 | // glms_env_new_ast_field(env, GLMS_TOKEN_TYPE_SPECIAL_NUMBER, "z") 245 | // }, 3); 246 | } 247 | -------------------------------------------------------------------------------- /src/modules/vec4.c: -------------------------------------------------------------------------------- 1 | #include "cglm/struct/vec4.h" 2 | #include "glms/allocator.h" 3 | #include "glms/ast.h" 4 | #include 5 | #include 6 | 7 | 8 | char *glms_struct_vec4_to_string(GLMSAST *ast, GLMSAllocator alloc, GLMSEnv* env) { 9 | Vector3 v = ast->as.v3; 10 | 11 | char tmp[256]; 12 | sprintf(tmp, "VEC4(%1.6f, %1.6f, %1.6f, %1.6f)", v.x, v.y, v.z, v.w); 13 | 14 | return alloc.strdup(alloc.user_ptr, tmp); 15 | } 16 | 17 | int glms_struct_vec4_swizzle(GLMSEval *eval, GLMSStack *stack, GLMSAST *ast, 18 | GLMSAST *accessor, GLMSAST *out) { 19 | const char *id = glms_ast_get_string_value(accessor); 20 | if (!id) 21 | return 0; 22 | 23 | if (strlen(id) > 1) { 24 | GLMS_WARNING_RETURN(0, stderr, "Invalid swizzle `%s`\n", id); 25 | } 26 | 27 | int idx = ((int)id[0]) - 120; 28 | 29 | if (idx < 0 || idx >= 4) { 30 | GLMS_WARNING_RETURN(0, stderr, "Invalid swizzle `%s`\n", id); 31 | } 32 | 33 | float* values = (float*)&ast->as.v4; 34 | 35 | float v = values[idx]; 36 | 37 | *out = (GLMSAST){.type = GLMS_AST_TYPE_NUMBER, .as.number.value = v}; 38 | return 1; 39 | } 40 | 41 | int glms_struct_vec4_op_overload_mul(GLMSEval *eval, GLMSStack *stack, 42 | GLMSAST *left, GLMSAST *right, 43 | GLMSAST *out) { 44 | 45 | 46 | 47 | if (!glms_ast_is_vector(left) && !glms_ast_is_vector(right)) 48 | return 0; 49 | 50 | Vector4 v = VEC41(0); 51 | 52 | 53 | if (left->type == GLMS_AST_TYPE_VEC4 && right->type == GLMS_AST_TYPE_NUMBER) { 54 | v = left->as.v4; 55 | v.x *= glms_ast_number(*right); 56 | v.y *= glms_ast_number(*right); 57 | v.z *= glms_ast_number(*right); 58 | v.w *= glms_ast_number(*right); 59 | } else if (left->type == GLMS_AST_TYPE_NUMBER && 60 | right->type == GLMS_AST_TYPE_VEC4) { 61 | v = right->as.v4; 62 | v.x *= glms_ast_number(*left); 63 | v.y *= glms_ast_number(*left); 64 | v.z *= glms_ast_number(*left); 65 | v.w *= glms_ast_number(*left); 66 | } else if (left->type == GLMS_AST_TYPE_VEC4 && 67 | right->type == GLMS_AST_TYPE_VEC4) { 68 | v.x = left->as.v4.x * right->as.v4.x; 69 | v.y = left->as.v4.y * right->as.v4.y; 70 | v.z = left->as.v4.z * right->as.v4.z; 71 | v.w = left->as.v4.w * right->as.v4.w; 72 | } 73 | 74 | *out = (GLMSAST){.type = GLMS_AST_TYPE_VEC4, .as.v4 = v}; 75 | return 1; 76 | } 77 | 78 | 79 | void glms_struct_vec4_constructor(GLMSEval *eval, GLMSStack *stack, 80 | GLMSASTBuffer *args, GLMSAST* self) { 81 | if (!self) return; 82 | GLMSAST *ast = self ;//? self : glms_env_new_ast(eval->env, GLMS_AST_TYPE_VEC4, true); 83 | 84 | ast->type = GLMS_AST_TYPE_VEC4; 85 | ast->swizzle = glms_struct_vec4_swizzle; 86 | ast->constructor = glms_struct_vec4_constructor; 87 | ast->to_string = glms_struct_vec4_to_string; 88 | 89 | glms_ast_register_operator_overload(eval->env, ast, GLMS_TOKEN_TYPE_MUL, 90 | glms_struct_vec4_op_overload_mul); 91 | 92 | if (!args) 93 | return; 94 | 95 | if (args->length == 2) { 96 | Vector3 xyz = args->items[0].as.v3; 97 | float w = glms_ast_number(args->items[1]); 98 | ast->as.v4 = VEC4(xyz.x, xyz.y, xyz.z, w); 99 | } else if (args->length >= 4) { 100 | float x = glms_ast_number(args->items[0]); 101 | float y = glms_ast_number(args->items[1]); 102 | float z = glms_ast_number(args->items[2]); 103 | float w = glms_ast_number(args->items[3]); 104 | 105 | ast->as.v4 = VEC4(x, y, z, w); 106 | } else if (args->length == 1) { 107 | float x = (glms_eval(eval, args->items[0], stack)).as.number.value; 108 | ast->as.v4 = VEC41(x); 109 | } 110 | 111 | } 112 | 113 | void glms_struct_vec4(GLMSEnv *env) { 114 | GLMSAST* typeast = glms_env_new_ast(env, GLMS_AST_TYPE_VEC4, false); 115 | glms_env_register_type(env, "vec4", typeast, 116 | glms_struct_vec4_constructor, glms_struct_vec4_swizzle, 117 | glms_struct_vec4_to_string, 0); 118 | 119 | glms_env_register_type(env, GLMS_AST_TYPE_STR[GLMS_AST_TYPE_VEC4], typeast, 120 | glms_struct_vec4_constructor, glms_struct_vec4_swizzle, 121 | glms_struct_vec4_to_string, 0); 122 | } 123 | -------------------------------------------------------------------------------- /src/stack.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "arena/arena.h" 6 | #include "glms/ast.h" 7 | #include "hashy/hashy.h" 8 | 9 | int glms_stack_init(GLMSStack* stack) { 10 | if (!stack) return 0; 11 | if (stack->initialized) return 1; 12 | stack->initialized = true; 13 | hashy_map_init(&stack->locals, 14 | (HashyConfig){.capacity = 256}); 15 | stack->return_flag = false; 16 | stack->depth = 0; 17 | 18 | return 1; 19 | } 20 | 21 | GLMSAST* glms_stack_push(GLMSStack* stack, const char* name, GLMSAST* ast) { 22 | if (!stack || !name || !ast) return 0; 23 | if (!stack->initialized) 24 | GLMS_WARNING_RETURN(0, stderr, "stack not initialized.\n"); 25 | 26 | hashy_map_set(&stack->locals, name, ast); 27 | 28 | return ast; 29 | } 30 | GLMSAST* glms_stack_get(GLMSStack* stack, const char* name) { 31 | if (!stack || !name) return 0; 32 | if (!stack->initialized) 33 | GLMS_WARNING_RETURN(0, stderr, "stack not initialized.\n"); 34 | 35 | return hashy_map_get(&stack->locals, name); 36 | } 37 | GLMSAST* glms_stack_pop(GLMSStack* stack, const char* name) { 38 | if (!stack || !name) return 0; 39 | if (!stack->initialized) 40 | GLMS_WARNING_RETURN(0, stderr, "stack not initialized.\n"); 41 | 42 | GLMSAST* ast = glms_stack_get(stack, name); 43 | 44 | if (!ast) return 0; 45 | 46 | hashy_map_unset(&stack->locals, name); 47 | 48 | return ast; 49 | } 50 | 51 | void glms_stack_dump(GLMSStack* stack, GLMSEnv* env) { 52 | if (!stack) return; 53 | if (!stack->initialized) 54 | GLMS_WARNING_RETURN(, stderr, "stack not initialized.\n"); 55 | 56 | fprintf(stderr, "not implemented.\n"); 57 | } 58 | 59 | int glms_stack_copy(GLMSStack src, GLMSStack* dest) { 60 | if (!dest) return 0; 61 | if (!dest->initialized) glms_stack_init(dest); 62 | 63 | HashyIterator it = {0}; 64 | 65 | while (hashy_map_iterate(&src.locals, &it)) { 66 | if (!it.bucket->is_set) continue; 67 | if (!it.bucket->value) continue; 68 | 69 | const char* key = it.bucket->key.value; 70 | GLMSAST* value = (GLMSAST*)it.bucket->value; 71 | 72 | glms_stack_push(dest, key, value); 73 | } 74 | 75 | return 1; 76 | } 77 | 78 | int glms_stack_clear(GLMSStack* stack) { 79 | if (!stack) return 0; 80 | if (!stack->initialized) 81 | GLMS_WARNING_RETURN(0, stderr, "stack not initialized.\n"); 82 | 83 | hashy_map_clear(&stack->locals); 84 | return 1; 85 | } 86 | 87 | int glms_stack_clear_trash(GLMSStack* stack) { 88 | if (!stack) return 0; 89 | if (!stack->initialized) 90 | GLMS_WARNING_RETURN(0, stderr, "stack not initialized.\n"); 91 | 92 | // if (stack->locals.used < 16) { 93 | // return 1; 94 | // } 95 | 96 | HashyIterator it = {0}; 97 | 98 | while (hashy_map_iterate(&stack->locals, &it)) { 99 | if (!it.bucket->is_set) continue; 100 | if (!it.bucket->value) continue; 101 | 102 | const char* key = it.bucket->key.value; 103 | GLMSAST* value = (GLMSAST*)it.bucket->value; 104 | 105 | if (value->keep) continue; 106 | if (value->ref.arena == 0) continue; 107 | 108 | hashy_map_unset(&stack->locals, key); 109 | arena_free(value->ref); 110 | } 111 | 112 | return 1; 113 | } 114 | -------------------------------------------------------------------------------- /src/string_builder.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int glms_string_builder_append(GLMSStringBuilder *builder, const char *value) { 8 | if (!builder || !value) return 0; 9 | 10 | int64_t len = strlen(value); 11 | if (len <= 0) return 0; 12 | 13 | 14 | if(builder->capacity < builder->length + len + 1) { 15 | builder->buffer = (char*)realloc(builder->buffer, (builder->length + len + 1) * sizeof(char)); 16 | if (!builder->buffer) { 17 | GLMS_WARNING_RETURN(0, stderr, "Allocation failure.\n"); 18 | } 19 | builder->capacity = builder->length + len + 1; 20 | } 21 | 22 | strcpy(builder->buffer + builder->length, value); 23 | 24 | builder->length += len; 25 | 26 | return 1; 27 | } 28 | 29 | int glms_string_builder_append_indented(GLMSStringBuilder *builder, 30 | const char *value, int indent, 31 | const char *indent_v) { 32 | if (!builder || !value) return 0; 33 | if (!indent || !indent_v) return glms_string_builder_append(builder, value); 34 | 35 | for (int i = 0; i < indent; i++) { 36 | if (!glms_string_builder_append(builder, indent_v)) return 0; 37 | } 38 | 39 | return glms_string_builder_append(builder, value); 40 | } 41 | 42 | int glms_string_builder_destroy(GLMSStringBuilder *builder) { 43 | if (!builder) return 0; 44 | 45 | if (builder->buffer != 0) { 46 | free(builder->buffer); 47 | } 48 | 49 | builder->buffer = 0; 50 | builder->length = 0; 51 | 52 | return 1; 53 | } 54 | -------------------------------------------------------------------------------- /src/string_view.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | const char* glms_string_view_get_value(GLMSStringView* view) { 6 | if (!view) return 0; 7 | if (view->length <= 0 || view->ptr == 0) return 0; 8 | if (view->length >= GLMS_STRING_VIEW_CAPACITY) 9 | GLMS_WARNING_RETURN(0, stderr, "string too large.\n"); 10 | memset(&view->tmp_buffer[0], 0, GLMS_STRING_VIEW_CAPACITY * sizeof(char)); 11 | memcpy(&view->tmp_buffer[0], &view->ptr[0], 12 | sizeof(char) * MIN(view->length, (GLMS_STRING_VIEW_CAPACITY - 1))); 13 | return view->tmp_buffer; 14 | } 15 | -------------------------------------------------------------------------------- /src/token.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | bool glms_token_type_is_flag(GLMSTokenType type) { 4 | return type == GLMS_TOKEN_TYPE_SPECIAL_USER_TYPE || 5 | type == GLMS_TOKEN_TYPE_SPECIAL_CONST || 6 | type == GLMS_TOKEN_TYPE_SPECIAL_NUMBER || 7 | type == GLMS_TOKEN_TYPE_SPECIAL_INT || 8 | type == GLMS_TOKEN_TYPE_SPECIAL_FLOAT || 9 | type == GLMS_TOKEN_TYPE_SPECIAL_UINT64 || 10 | type == GLMS_TOKEN_TYPE_SPECIAL_VOID || 11 | type == GLMS_TOKEN_TYPE_SPECIAL_IN || 12 | type == GLMS_TOKEN_TYPE_SPECIAL_OUT || 13 | type == GLMS_TOKEN_TYPE_SPECIAL_INOUT || 14 | type == GLMS_TOKEN_TYPE_SPECIAL_UNIFORM || 15 | type == GLMS_TOKEN_TYPE_SPECIAL_READONLY || // TODO: implement type for this and remove from here 16 | type == GLMS_TOKEN_TYPE_SPECIAL_BUFFER || // TODO: implement type for this and remove from here 17 | type == GLMS_TOKEN_TYPE_SPECIAL_SAMPLER_2D || // TODO: implement type for this and remove from here 18 | type == GLMS_TOKEN_TYPE_SPECIAL_SAMPLER_3D || // TODO: implement type for this and remove from here 19 | type == GLMS_TOKEN_TYPE_SPECIAL_SAMPLER_CUBE || // TODO: implement type for this and remove from here 20 | type == GLMS_TOKEN_TYPE_SPECIAL_ARRAY || 21 | type == GLMS_TOKEN_TYPE_SPECIAL_OBJECT || 22 | type == GLMS_TOKEN_TYPE_SPECIAL_STRING || 23 | type == GLMS_TOKEN_TYPE_SPECIAL_LET || 24 | type == GLMS_TOKEN_TYPE_SPECIAL_BOOL; 25 | } 26 | -------------------------------------------------------------------------------- /src/type.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | GLMS_IMPLEMENT_BUFFER(GLMSFunctionSignature); 5 | 6 | GLMSFunctionSignature glms_make_signature(GLMSType ret_type, GLMSType* args, 7 | int args_length) { 8 | return (GLMSFunctionSignature){ 9 | .return_type = ret_type, .args = args, .args_length = args_length}; 10 | } 11 | 12 | const char* glms_type_to_string(GLMSType t) { 13 | if (t.typename) return t.typename; 14 | return GLMS_AST_TYPE_STR[t.ast_type]; 15 | } 16 | char* glms_function_signature_to_string(GLMSFunctionSignature signa, 17 | const char* func_name) { 18 | char* s = 0; 19 | text_append(&s, glms_type_to_string(signa.return_type)); 20 | text_append(&s, " "); 21 | text_append(&s, func_name); 22 | text_append(&s, "("); 23 | 24 | if (signa.args != 0) { 25 | for (int i = 0; i < signa.args_length; i++) { 26 | text_append(&s, glms_type_to_string(signa.args[i])); 27 | 28 | if (signa.args[i].valuename) { 29 | text_append(&s, " "); 30 | text_append(&s, signa.args[i].valuename); 31 | } 32 | 33 | if (i < signa.args_length - 1) { 34 | text_append(&s, ", "); 35 | } 36 | } 37 | } 38 | text_append(&s, ")"); 39 | 40 | if (signa.description) { 41 | text_append(&s, " // "); 42 | text_append(&s, signa.description); 43 | text_append(&s, "\n"); 44 | } 45 | 46 | return s; 47 | } 48 | int glms_type_destroy(GLMSType* type) { 49 | if (!type) return 0; 50 | if (type->typename) { 51 | free(type->typename); 52 | type->typename = 0; 53 | } 54 | 55 | if (type->valuename) { 56 | free(type->valuename); 57 | type->valuename = 0; 58 | } 59 | 60 | return 1; 61 | } 62 | int glms_signature_destroy(GLMSFunctionSignature* signa) { 63 | if (!signa) return 0; 64 | 65 | if (signa->description) { 66 | free(signa->description); 67 | signa->description = 0; 68 | } 69 | 70 | if (signa->args != 0) { 71 | for (int i = 0; i < signa->args_length; i++) { 72 | glms_type_destroy(&signa->args[i]); 73 | } 74 | 75 | free(signa->args); 76 | signa->args = 0; 77 | signa->args_length = 0; 78 | } 79 | 80 | return 1; 81 | } 82 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.20) 2 | 3 | project(glms_test) 4 | 5 | 6 | file(GLOB PUBLIC_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/include/*.h) 7 | file(GLOB glms_sources ${CMAKE_CURRENT_SOURCE_DIR}/src/*.c) 8 | 9 | file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/samples DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/.) 10 | 11 | 12 | add_executable(glms_test ${glms_sources}) 13 | 14 | target_link_libraries(glms_test PUBLIC glms_static) 15 | -------------------------------------------------------------------------------- /test/samples/add_add.gs: -------------------------------------------------------------------------------- 1 | number x = 0; 2 | 3 | x++; 4 | 5 | print(x); 6 | -------------------------------------------------------------------------------- /test/samples/array.gs: -------------------------------------------------------------------------------- 1 | array arr = [1, 2, 3]; 2 | 3 | number x = arr[2]; 4 | 5 | print(x); 6 | -------------------------------------------------------------------------------- /test/samples/arrow_func.gs: -------------------------------------------------------------------------------- 1 | number hello = () => 123; 2 | 3 | print(hello()); 4 | -------------------------------------------------------------------------------- /test/samples/clamp.gs: -------------------------------------------------------------------------------- 1 | number value = 2312.0; 2 | value = clamp(value, 0.0, 1.0); 3 | print(value); -------------------------------------------------------------------------------- /test/samples/cos_sin.gs: -------------------------------------------------------------------------------- 1 | number x = cos(1.6); 2 | number y = sin(1.6); 3 | 4 | print(x); 5 | print(y); 6 | -------------------------------------------------------------------------------- /test/samples/for.gs: -------------------------------------------------------------------------------- 1 | number y = 0; 2 | 3 | for (number i = 0; i < 16; i++) { 4 | y++; 5 | } 6 | 7 | print(y); 8 | -------------------------------------------------------------------------------- /test/samples/func.gs: -------------------------------------------------------------------------------- 1 | function hello() { 2 | number x = 2; 3 | return x; 4 | } 5 | 6 | print(hello()); 7 | -------------------------------------------------------------------------------- /test/samples/if.gs: -------------------------------------------------------------------------------- 1 | number x = 3; 2 | 3 | if (false) { 4 | x = 0; 5 | } else { 6 | x = 1; 7 | print("false!"); 8 | } 9 | 10 | print(x); 11 | -------------------------------------------------------------------------------- /test/samples/minmax.gs: -------------------------------------------------------------------------------- 1 | number x = min(212.2, 11.332, 9.0, 9.77); 2 | number y = max(212.2, 11.332, 9.0, 9.77); 3 | 4 | print(y); 5 | print(x); -------------------------------------------------------------------------------- /test/samples/mix.gs: -------------------------------------------------------------------------------- 1 | vec3 v1 = vec3(1.0, 0.1, 0.2); 2 | vec3 v2 = vec3(0.0, 1.0, 0.1); 3 | 4 | vec3 v3 = mix(v1, v2, 0.5); 5 | 6 | print(v3); 7 | -------------------------------------------------------------------------------- /test/samples/object.gs: -------------------------------------------------------------------------------- 1 | object x = { 2 | "hello": 123, 3 | "nested": { 4 | "yo": 42, 5 | "other": { 6 | name: "John" 7 | } 8 | } 9 | }; 10 | 11 | 12 | x.hello = 33; 13 | number y = x.hello; 14 | print(x.nested.other.name); 15 | -------------------------------------------------------------------------------- /test/samples/plus_equals.gs: -------------------------------------------------------------------------------- 1 | let x = 2; 2 | 3 | 4 | x += 3; 5 | 6 | print(x); 7 | -------------------------------------------------------------------------------- /test/samples/self.gs: -------------------------------------------------------------------------------- 1 | typedef struct { 2 | string name; 3 | 4 | function changeName(string newName) { 5 | self.name = newName; 6 | } 7 | } Person; 8 | 9 | 10 | Person p = Person("John Doe"); 11 | 12 | print(p.name); 13 | 14 | p.changeName("David Doe"); 15 | 16 | print(p.name); 17 | 18 | string x = p.name; 19 | -------------------------------------------------------------------------------- /test/samples/struct.gs: -------------------------------------------------------------------------------- 1 | typedef struct { 2 | number age; 3 | string name; 4 | } Person; 5 | 6 | Person p = Person(33, "John doe"); 7 | 8 | print(p); 9 | 10 | Person p2; 11 | p2.age = 22; 12 | p2.name = "Sarah Doe"; 13 | print(p2); 14 | 15 | g = struct { 16 | string name = "test"; 17 | }; 18 | 19 | print(g); 20 | -------------------------------------------------------------------------------- /test/samples/sub_sub.gs: -------------------------------------------------------------------------------- 1 | number x = 3; 2 | 3 | x--; 4 | 5 | print(x); 6 | -------------------------------------------------------------------------------- /test/samples/template_string.gs: -------------------------------------------------------------------------------- 1 | string name = "John"; 2 | string x = `hello ${name}`; 3 | 4 | print(x); 5 | -------------------------------------------------------------------------------- /test/samples/var.gs: -------------------------------------------------------------------------------- 1 | number x = 2; 2 | 3 | print(x); 4 | -------------------------------------------------------------------------------- /test/samples/varfunc.gs: -------------------------------------------------------------------------------- 1 | const number x = { 2 | y: () => { 3 | return 44; 4 | } 5 | }; 6 | 7 | 8 | number w = x.y(); 9 | 10 | print(w); 11 | -------------------------------------------------------------------------------- /test/samples/vec.gs: -------------------------------------------------------------------------------- 1 | vec3 v1 = vec3(0, 1, 0); 2 | vec3 v2 = vec3(0, 1, 0); 3 | 4 | //keep(v1); 5 | //keep(v2); 6 | 7 | print(v1); 8 | print(v2); 9 | 10 | number d = dot(v1, v2); 11 | 12 | print(d); 13 | -------------------------------------------------------------------------------- /test/samples/while.gs: -------------------------------------------------------------------------------- 1 | number x = 500; 2 | number y = 0; 3 | 4 | while (x > 0) { 5 | x--; 6 | y++; 7 | } 8 | 9 | print("y:"); 10 | print(y); 11 | --------------------------------------------------------------------------------