├── COPYING ├── Makefile ├── README ├── example.c ├── frame.c ├── frame.h ├── goof.c ├── goof.h └── simple.c /COPYING: -------------------------------------------------------------------------------- 1 | GNU LIBRARY GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1991 Free Software Foundation, Inc. 5 | 675 Mass Ave, Cambridge, MA 02139, USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | [This is the first released version of the library GPL. It is 10 | numbered 2 because it goes with version 2 of the ordinary GPL.] 11 | 12 | Preamble 13 | 14 | The licenses for most software are designed to take away your 15 | freedom to share and change it. By contrast, the GNU General Public 16 | Licenses are intended to guarantee your freedom to share and change 17 | free software--to make sure the software is free for all its users. 18 | 19 | This license, the Library General Public License, applies to some 20 | specially designated Free Software Foundation software, and to any 21 | other libraries whose authors decide to use it. You can use it for 22 | your libraries, too. 23 | 24 | When we speak of free software, we are referring to freedom, not 25 | price. Our General Public Licenses are designed to make sure that you 26 | have the freedom to distribute copies of free software (and charge for 27 | this service if you wish), that you receive source code or can get it 28 | if you want it, that you can change the software or use pieces of it 29 | in new free programs; and that you know you can do these things. 30 | 31 | To protect your rights, we need to make restrictions that forbid 32 | anyone to deny you these rights or to ask you to surrender the rights. 33 | These restrictions translate to certain responsibilities for you if 34 | you distribute copies of the library, or if you modify it. 35 | 36 | For example, if you distribute copies of the library, whether gratis 37 | or for a fee, you must give the recipients all the rights that we gave 38 | you. You must make sure that they, too, receive or can get the source 39 | code. If you link a program with the library, you must provide 40 | complete object files to the recipients so that they can relink them 41 | with the library, after making changes to the library and recompiling 42 | it. And you must show them these terms so they know their rights. 43 | 44 | Our method of protecting your rights has two steps: (1) copyright 45 | the library, and (2) offer you this license which gives you legal 46 | permission to copy, distribute and/or modify the library. 47 | 48 | Also, for each distributor's protection, we want to make certain 49 | that everyone understands that there is no warranty for this free 50 | library. If the library is modified by someone else and passed on, we 51 | want its recipients to know that what they have is not the original 52 | version, so that any problems introduced by others will not reflect on 53 | the original authors' reputations. 54 | 55 | Finally, any free program is threatened constantly by software 56 | patents. We wish to avoid the danger that companies distributing free 57 | software will individually obtain patent licenses, thus in effect 58 | transforming the program into proprietary software. To prevent this, 59 | we have made it clear that any patent must be licensed for everyone's 60 | free use or not licensed at all. 61 | 62 | Most GNU software, including some libraries, is covered by the ordinary 63 | GNU General Public License, which was designed for utility programs. This 64 | license, the GNU Library General Public License, applies to certain 65 | designated libraries. This license is quite different from the ordinary 66 | one; be sure to read it in full, and don't assume that anything in it is 67 | the same as in the ordinary license. 68 | 69 | The reason we have a separate public license for some libraries is that 70 | they blur the distinction we usually make between modifying or adding to a 71 | program and simply using it. Linking a program with a library, without 72 | changing the library, is in some sense simply using the library, and is 73 | analogous to running a utility program or application program. However, in 74 | a textual and legal sense, the linked executable is a combined work, a 75 | derivative of the original library, and the ordinary General Public License 76 | treats it as such. 77 | 78 | Because of this blurred distinction, using the ordinary General 79 | Public License for libraries did not effectively promote software 80 | sharing, because most developers did not use the libraries. We 81 | concluded that weaker conditions might promote sharing better. 82 | 83 | However, unrestricted linking of non-free programs would deprive the 84 | users of those programs of all benefit from the free status of the 85 | libraries themselves. This Library General Public License is intended to 86 | permit developers of non-free programs to use free libraries, while 87 | preserving your freedom as a user of such programs to change the free 88 | libraries that are incorporated in them. (We have not seen how to achieve 89 | this as regards changes in header files, but we have achieved it as regards 90 | changes in the actual functions of the Library.) The hope is that this 91 | will lead to faster development of free libraries. 92 | 93 | The precise terms and conditions for copying, distribution and 94 | modification follow. Pay close attention to the difference between a 95 | "work based on the library" and a "work that uses the library". The 96 | former contains code derived from the library, while the latter only 97 | works together with the library. 98 | 99 | Note that it is possible for a library to be covered by the ordinary 100 | General Public License rather than by this special one. 101 | 102 | GNU LIBRARY GENERAL PUBLIC LICENSE 103 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 104 | 105 | 0. This License Agreement applies to any software library which 106 | contains a notice placed by the copyright holder or other authorized 107 | party saying it may be distributed under the terms of this Library 108 | General Public License (also called "this License"). Each licensee is 109 | addressed as "you". 110 | 111 | A "library" means a collection of software functions and/or data 112 | prepared so as to be conveniently linked with application programs 113 | (which use some of those functions and data) to form executables. 114 | 115 | The "Library", below, refers to any such software library or work 116 | which has been distributed under these terms. A "work based on the 117 | Library" means either the Library or any derivative work under 118 | copyright law: that is to say, a work containing the Library or a 119 | portion of it, either verbatim or with modifications and/or translated 120 | straightforwardly into another language. (Hereinafter, translation is 121 | included without limitation in the term "modification".) 122 | 123 | "Source code" for a work means the preferred form of the work for 124 | making modifications to it. For a library, complete source code means 125 | all the source code for all modules it contains, plus any associated 126 | interface definition files, plus the scripts used to control compilation 127 | and installation of the library. 128 | 129 | Activities other than copying, distribution and modification are not 130 | covered by this License; they are outside its scope. The act of 131 | running a program using the Library is not restricted, and output from 132 | such a program is covered only if its contents constitute a work based 133 | on the Library (independent of the use of the Library in a tool for 134 | writing it). Whether that is true depends on what the Library does 135 | and what the program that uses the Library does. 136 | 137 | 1. You may copy and distribute verbatim copies of the Library's 138 | complete source code as you receive it, in any medium, provided that 139 | you conspicuously and appropriately publish on each copy an 140 | appropriate copyright notice and disclaimer of warranty; keep intact 141 | all the notices that refer to this License and to the absence of any 142 | warranty; and distribute a copy of this License along with the 143 | Library. 144 | 145 | You may charge a fee for the physical act of transferring a copy, 146 | and you may at your option offer warranty protection in exchange for a 147 | fee. 148 | 149 | 2. You may modify your copy or copies of the Library or any portion 150 | of it, thus forming a work based on the Library, and copy and 151 | distribute such modifications or work under the terms of Section 1 152 | above, provided that you also meet all of these conditions: 153 | 154 | a) The modified work must itself be a software library. 155 | 156 | b) You must cause the files modified to carry prominent notices 157 | stating that you changed the files and the date of any change. 158 | 159 | c) You must cause the whole of the work to be licensed at no 160 | charge to all third parties under the terms of this License. 161 | 162 | d) If a facility in the modified Library refers to a function or a 163 | table of data to be supplied by an application program that uses 164 | the facility, other than as an argument passed when the facility 165 | is invoked, then you must make a good faith effort to ensure that, 166 | in the event an application does not supply such function or 167 | table, the facility still operates, and performs whatever part of 168 | its purpose remains meaningful. 169 | 170 | (For example, a function in a library to compute square roots has 171 | a purpose that is entirely well-defined independent of the 172 | application. Therefore, Subsection 2d requires that any 173 | application-supplied function or table used by this function must 174 | be optional: if the application does not supply it, the square 175 | root function must still compute square roots.) 176 | 177 | These requirements apply to the modified work as a whole. If 178 | identifiable sections of that work are not derived from the Library, 179 | and can be reasonably considered independent and separate works in 180 | themselves, then this License, and its terms, do not apply to those 181 | sections when you distribute them as separate works. But when you 182 | distribute the same sections as part of a whole which is a work based 183 | on the Library, the distribution of the whole must be on the terms of 184 | this License, whose permissions for other licensees extend to the 185 | entire whole, and thus to each and every part regardless of who wrote 186 | it. 187 | 188 | Thus, it is not the intent of this section to claim rights or contest 189 | your rights to work written entirely by you; rather, the intent is to 190 | exercise the right to control the distribution of derivative or 191 | collective works based on the Library. 192 | 193 | In addition, mere aggregation of another work not based on the Library 194 | with the Library (or with a work based on the Library) on a volume of 195 | a storage or distribution medium does not bring the other work under 196 | the scope of this License. 197 | 198 | 3. You may opt to apply the terms of the ordinary GNU General Public 199 | License instead of this License to a given copy of the Library. To do 200 | this, you must alter all the notices that refer to this License, so 201 | that they refer to the ordinary GNU General Public License, version 2, 202 | instead of to this License. (If a newer version than version 2 of the 203 | ordinary GNU General Public License has appeared, then you can specify 204 | that version instead if you wish.) Do not make any other change in 205 | these notices. 206 | 207 | Once this change is made in a given copy, it is irreversible for 208 | that copy, so the ordinary GNU General Public License applies to all 209 | subsequent copies and derivative works made from that copy. 210 | 211 | This option is useful when you wish to copy part of the code of 212 | the Library into a program that is not a library. 213 | 214 | 4. You may copy and distribute the Library (or a portion or 215 | derivative of it, under Section 2) in object code or executable form 216 | under the terms of Sections 1 and 2 above provided that you accompany 217 | it with the complete corresponding machine-readable source code, which 218 | must be distributed under the terms of Sections 1 and 2 above on a 219 | medium customarily used for software interchange. 220 | 221 | If distribution of object code is made by offering access to copy 222 | from a designated place, then offering equivalent access to copy the 223 | source code from the same place satisfies the requirement to 224 | distribute the source code, even though third parties are not 225 | compelled to copy the source along with the object code. 226 | 227 | 5. A program that contains no derivative of any portion of the 228 | Library, but is designed to work with the Library by being compiled or 229 | linked with it, is called a "work that uses the Library". Such a 230 | work, in isolation, is not a derivative work of the Library, and 231 | therefore falls outside the scope of this License. 232 | 233 | However, linking a "work that uses the Library" with the Library 234 | creates an executable that is a derivative of the Library (because it 235 | contains portions of the Library), rather than a "work that uses the 236 | library". The executable is therefore covered by this License. 237 | Section 6 states terms for distribution of such executables. 238 | 239 | When a "work that uses the Library" uses material from a header file 240 | that is part of the Library, the object code for the work may be a 241 | derivative work of the Library even though the source code is not. 242 | Whether this is true is especially significant if the work can be 243 | linked without the Library, or if the work is itself a library. The 244 | threshold for this to be true is not precisely defined by law. 245 | 246 | If such an object file uses only numerical parameters, data 247 | structure layouts and accessors, and small macros and small inline 248 | functions (ten lines or less in length), then the use of the object 249 | file is unrestricted, regardless of whether it is legally a derivative 250 | work. (Executables containing this object code plus portions of the 251 | Library will still fall under Section 6.) 252 | 253 | Otherwise, if the work is a derivative of the Library, you may 254 | distribute the object code for the work under the terms of Section 6. 255 | Any executables containing that work also fall under Section 6, 256 | whether or not they are linked directly with the Library itself. 257 | 258 | 6. As an exception to the Sections above, you may also compile or 259 | link a "work that uses the Library" with the Library to produce a 260 | work containing portions of the Library, and distribute that work 261 | under terms of your choice, provided that the terms permit 262 | modification of the work for the customer's own use and reverse 263 | engineering for debugging such modifications. 264 | 265 | You must give prominent notice with each copy of the work that the 266 | Library is used in it and that the Library and its use are covered by 267 | this License. You must supply a copy of this License. If the work 268 | during execution displays copyright notices, you must include the 269 | copyright notice for the Library among them, as well as a reference 270 | directing the user to the copy of this License. Also, you must do one 271 | of these things: 272 | 273 | a) Accompany the work with the complete corresponding 274 | machine-readable source code for the Library including whatever 275 | changes were used in the work (which must be distributed under 276 | Sections 1 and 2 above); and, if the work is an executable linked 277 | with the Library, with the complete machine-readable "work that 278 | uses the Library", as object code and/or source code, so that the 279 | user can modify the Library and then relink to produce a modified 280 | executable containing the modified Library. (It is understood 281 | that the user who changes the contents of definitions files in the 282 | Library will not necessarily be able to recompile the application 283 | to use the modified definitions.) 284 | 285 | b) Accompany the work with a written offer, valid for at 286 | least three years, to give the same user the materials 287 | specified in Subsection 6a, above, for a charge no more 288 | than the cost of performing this distribution. 289 | 290 | c) If distribution of the work is made by offering access to copy 291 | from a designated place, offer equivalent access to copy the above 292 | specified materials from the same place. 293 | 294 | d) Verify that the user has already received a copy of these 295 | materials or that you have already sent this user a copy. 296 | 297 | For an executable, the required form of the "work that uses the 298 | Library" must include any data and utility programs needed for 299 | reproducing the executable from it. However, as a special exception, 300 | the source code distributed need not include anything that is normally 301 | distributed (in either source or binary form) with the major 302 | components (compiler, kernel, and so on) of the operating system on 303 | which the executable runs, unless that component itself accompanies 304 | the executable. 305 | 306 | It may happen that this requirement contradicts the license 307 | restrictions of other proprietary libraries that do not normally 308 | accompany the operating system. Such a contradiction means you cannot 309 | use both them and the Library together in an executable that you 310 | distribute. 311 | 312 | 7. You may place library facilities that are a work based on the 313 | Library side-by-side in a single library together with other library 314 | facilities not covered by this License, and distribute such a combined 315 | library, provided that the separate distribution of the work based on 316 | the Library and of the other library facilities is otherwise 317 | permitted, and provided that you do these two things: 318 | 319 | a) Accompany the combined library with a copy of the same work 320 | based on the Library, uncombined with any other library 321 | facilities. This must be distributed under the terms of the 322 | Sections above. 323 | 324 | b) Give prominent notice with the combined library of the fact 325 | that part of it is a work based on the Library, and explaining 326 | where to find the accompanying uncombined form of the same work. 327 | 328 | 8. You may not copy, modify, sublicense, link with, or distribute 329 | the Library except as expressly provided under this License. Any 330 | attempt otherwise to copy, modify, sublicense, link with, or 331 | distribute the Library is void, and will automatically terminate your 332 | rights under this License. However, parties who have received copies, 333 | or rights, from you under this License will not have their licenses 334 | terminated so long as such parties remain in full compliance. 335 | 336 | 9. You are not required to accept this License, since you have not 337 | signed it. However, nothing else grants you permission to modify or 338 | distribute the Library or its derivative works. These actions are 339 | prohibited by law if you do not accept this License. Therefore, by 340 | modifying or distributing the Library (or any work based on the 341 | Library), you indicate your acceptance of this License to do so, and 342 | all its terms and conditions for copying, distributing or modifying 343 | the Library or works based on it. 344 | 345 | 10. Each time you redistribute the Library (or any work based on the 346 | Library), the recipient automatically receives a license from the 347 | original licensor to copy, distribute, link with or modify the Library 348 | subject to these terms and conditions. You may not impose any further 349 | restrictions on the recipients' exercise of the rights granted herein. 350 | You are not responsible for enforcing compliance by third parties to 351 | this License. 352 | 353 | 11. If, as a consequence of a court judgment or allegation of patent 354 | infringement or for any other reason (not limited to patent issues), 355 | conditions are imposed on you (whether by court order, agreement or 356 | otherwise) that contradict the conditions of this License, they do not 357 | excuse you from the conditions of this License. If you cannot 358 | distribute so as to satisfy simultaneously your obligations under this 359 | License and any other pertinent obligations, then as a consequence you 360 | may not distribute the Library at all. For example, if a patent 361 | license would not permit royalty-free redistribution of the Library by 362 | all those who receive copies directly or indirectly through you, then 363 | the only way you could satisfy both it and this License would be to 364 | refrain entirely from distribution of the Library. 365 | 366 | If any portion of this section is held invalid or unenforceable under any 367 | particular circumstance, the balance of the section is intended to apply, 368 | and the section as a whole is intended to apply in other circumstances. 369 | 370 | It is not the purpose of this section to induce you to infringe any 371 | patents or other property right claims or to contest validity of any 372 | such claims; this section has the sole purpose of protecting the 373 | integrity of the free software distribution system which is 374 | implemented by public license practices. Many people have made 375 | generous contributions to the wide range of software distributed 376 | through that system in reliance on consistent application of that 377 | system; it is up to the author/donor to decide if he or she is willing 378 | to distribute software through any other system and a licensee cannot 379 | impose that choice. 380 | 381 | This section is intended to make thoroughly clear what is believed to 382 | be a consequence of the rest of this License. 383 | 384 | 12. If the distribution and/or use of the Library is restricted in 385 | certain countries either by patents or by copyrighted interfaces, the 386 | original copyright holder who places the Library under this License may add 387 | an explicit geographical distribution limitation excluding those countries, 388 | so that distribution is permitted only in or among countries not thus 389 | excluded. In such case, this License incorporates the limitation as if 390 | written in the body of this License. 391 | 392 | 13. The Free Software Foundation may publish revised and/or new 393 | versions of the Library General Public License from time to time. 394 | Such new versions will be similar in spirit to the present version, 395 | but may differ in detail to address new problems or concerns. 396 | 397 | Each version is given a distinguishing version number. If the Library 398 | specifies a version number of this License which applies to it and 399 | "any later version", you have the option of following the terms and 400 | conditions either of that version or of any later version published by 401 | the Free Software Foundation. If the Library does not specify a 402 | license version number, you may choose any version ever published by 403 | the Free Software Foundation. 404 | 405 | 14. If you wish to incorporate parts of the Library into other free 406 | programs whose distribution conditions are incompatible with these, 407 | write to the author to ask for permission. For software which is 408 | copyrighted by the Free Software Foundation, write to the Free 409 | Software Foundation; we sometimes make exceptions for this. Our 410 | decision will be guided by the two goals of preserving the free status 411 | of all derivatives of our free software and of promoting the sharing 412 | and reuse of software generally. 413 | 414 | NO WARRANTY 415 | 416 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO 417 | WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 418 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 419 | OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY 420 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 421 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 422 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE 423 | LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME 424 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 425 | 426 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN 427 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY 428 | AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU 429 | FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR 430 | CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE 431 | LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 432 | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 433 | FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF 434 | SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 435 | DAMAGES. 436 | 437 | END OF TERMS AND CONDITIONS 438 | 439 | Appendix: How to Apply These Terms to Your New Libraries 440 | 441 | If you develop a new library, and you want it to be of the greatest 442 | possible use to the public, we recommend making it free software that 443 | everyone can redistribute and change. You can do so by permitting 444 | redistribution under these terms (or, alternatively, under the terms of the 445 | ordinary General Public License). 446 | 447 | To apply these terms, attach the following notices to the library. It is 448 | safest to attach them to the start of each source file to most effectively 449 | convey the exclusion of warranty; and each file should have at least the 450 | "copyright" line and a pointer to where the full notice is found. 451 | 452 | 453 | Copyright (C) 454 | 455 | This library is free software; you can redistribute it and/or 456 | modify it under the terms of the GNU Library General Public 457 | License as published by the Free Software Foundation; either 458 | version 2 of the License, or (at your option) any later version. 459 | 460 | This library is distributed in the hope that it will be useful, 461 | but WITHOUT ANY WARRANTY; without even the implied warranty of 462 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 463 | Library General Public License for more details. 464 | 465 | You should have received a copy of the GNU Library General Public 466 | License along with this library; if not, write to the Free 467 | Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 468 | 469 | Also add information on how to contact you by electronic and paper mail. 470 | 471 | You should also get your employer (if you work as a programmer) or your 472 | school, if any, to sign a "copyright disclaimer" for the library, if 473 | necessary. Here is a sample; alter the names: 474 | 475 | Yoyodyne, Inc., hereby disclaims all copyright interest in the 476 | library `Frob' (a library for tweaking knobs) written by James Random Hacker. 477 | 478 | , 1 April 1990 479 | Ty Coon, President of Vice 480 | 481 | That's all there is to it! 482 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | simple: goof.c goof.h frame.c frame.h simple.c 2 | gcc -g `pkg-config --cflags --libs glib-2.0 gobject-2.0` goof.c\ 3 | frame.c simple.c \ 4 | -o simple 5 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Copyright (C) 2010 Brandon Lewis 2 | 3 | Introduction 4 | 5 | Goof is an experimental functional language with a novel implementation. It is 6 | a library of functions and macros which combine to create the illusion that 7 | you are writing in a high-level language. Despite this, goof programs are C 8 | programs. They are compiled and executed like any other. 9 | 10 | Don't be fooled into thinking it's efficient: Goof is essentially a dynamic 11 | language, with the runtime implemented directly in C. 12 | 13 | Goof programs are expressed as nested calls to functions and macros. Each 14 | function returns a pointer to an object which implements a language contruct. 15 | 16 | Known Downsides (or, "Why in God's name are you doing this?") 17 | 18 | - I just wrote it over the weekend for fun 19 | - No memory management at present 20 | - Dynamic implementation is probably inefficient 21 | - I am largely ignorant of how concurrency might affect this system 22 | - Possibly difficult to debug, and syntax erros are difficult to resolve due 23 | to the heavy abuse of preprocessor macros. 24 | 25 | Potential Upsides 26 | 27 | Though I acknowledge that this is really a pretty terrible thing to do to an 28 | unsuspecting C programmer, I feel that there might be certain useful features 29 | of this approach that are worth exploring. In addition to the well-known 30 | advantages of functional programming, goof might offer the following: 31 | 32 | - educational value 33 | - small implementation 34 | - easy to add new constructs to the language 35 | - easy to inter-operate between C and goof 36 | - requires nothing other than a C compiler (after removing the glib code) 37 | - you potentially mix and match different semantics within the same executable 38 | (e.g. applicative versus normal order, eager versus strict, allow 39 | non-deterministic evaluation etc). 40 | 41 | Liscence 42 | 43 | Goof is available under LGPL v3 44 | -------------------------------------------------------------------------------- /example.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | BEGIN 4 | 5 | window ( 6 | connect ("destroy", 7 | call_c (gtk_main_quit) 8 | ), 9 | add ( 10 | button ("click me", 11 | connect ("clicked", 12 | block ( 13 | print ("ouch!"), 14 | set ("this", "title", "ouch!") 15 | ) 16 | ) 17 | ) 18 | ) 19 | ) 20 | 21 | 22 | END 23 | -------------------------------------------------------------------------------- /frame.c: -------------------------------------------------------------------------------- 1 | #include "frame.h" 2 | 3 | #define G_VALUE_UPDATE(source, dest) {\ 4 | GValue *src = source, *dst = dest;\ 5 | g_value_unset (src);\ 6 | g_value_init (src, G_VALUE_TYPE(src));\ 7 | g_value_copy (src, dest);\ 8 | } 9 | 10 | struct _Frame { 11 | Frame *parent; 12 | GHashTable *symbols; 13 | }; 14 | 15 | 16 | Frame *frame_new (Frame *parent) 17 | { 18 | Frame *ret; 19 | 20 | ret = g_new0 (Frame, 1); 21 | ret->parent = parent; 22 | ret->symbols = g_hash_table_new (g_str_hash, g_str_equal); 23 | 24 | return ret; 25 | } 26 | 27 | /* creates a local instance of value */ 28 | 29 | void frame_set_local(Frame *frame, gchar *name, GValue *value) 30 | { 31 | GValue *stored; 32 | 33 | /* check whether the key exists, if so overwrite previous GValue */ 34 | /* TODO: freelists? */ 35 | 36 | if ((stored = g_hash_table_lookup (frame->symbols, name))) { 37 | g_value_unset (stored); 38 | } else { 39 | stored = g_new0 (GValue, 1); 40 | g_hash_table_insert (frame->symbols, name, stored); 41 | } 42 | 43 | g_value_init (stored, G_VALUE_TYPE (value)); 44 | g_value_copy (value, stored); 45 | } 46 | 47 | /* updates the symbol in the inner-most frame in which it is defined. If the 48 | * symbol is defined in the current scope, the effect is the same as calling 49 | * frame_set_local. Has no effect if the frame is undefined. */ 50 | 51 | gboolean frame_update (Frame *frame, gchar *name, GValue *value) 52 | { 53 | GValue *stored; 54 | 55 | if (!frame) 56 | return FALSE; 57 | 58 | if ((stored = frame_get_local (frame, name))) { 59 | G_VALUE_UPDATE (stored, value); 60 | return TRUE; 61 | } 62 | 63 | return frame_update (frame->parent, name, value); 64 | } 65 | 66 | /* recursive search of parent frames for value */ 67 | 68 | GValue *frame_get_value(Frame *frame, gchar *name) 69 | { 70 | GValue *stored = NULL; 71 | 72 | if (!frame) { 73 | return NULL; 74 | } 75 | 76 | if ((stored = frame_get_local(frame, name))) 77 | return stored; 78 | 79 | return frame_get_value (frame->parent, name); 80 | } 81 | 82 | /* returns local copy of value or NULL */ 83 | 84 | GValue *frame_get_local (Frame *frame, gchar *name) 85 | { 86 | GValue *stored = NULL; 87 | 88 | return g_hash_table_lookup (frame->symbols, name); 89 | } 90 | 91 | static void print_entry (gchar *key, GValue *value, void *unused) { 92 | GValue v = { 0 }; 93 | g_value_init (&v, G_TYPE_STRING); 94 | g_value_transform (value, &v); 95 | 96 | g_printf (" %s = %s\n", key, g_value_get_string (&v)); 97 | 98 | g_value_unset (&v); 99 | } 100 | 101 | void frame_dump_stack (Frame *frame) 102 | { 103 | if (frame->parent) { 104 | frame_dump_stack (frame->parent); 105 | g_printf ("\n"); 106 | } 107 | 108 | g_printf ("\n", frame); 109 | g_hash_table_foreach (frame->symbols, (GHFunc) print_entry, NULL); 110 | } 111 | -------------------------------------------------------------------------------- /frame.h: -------------------------------------------------------------------------------- 1 | #ifndef __FRAME_H__ 2 | 3 | #include 4 | #include 5 | 6 | typedef struct _Frame Frame; 7 | 8 | 9 | Frame *frame_new (Frame *parent); 10 | void frame_set_local(Frame *frame, gchar *name, GValue *value); 11 | gboolean frame_update (Frame *frame, gchar *name, GValue *value); 12 | GValue *frame_get_value(Frame *frame, gchar *name); 13 | GValue *frame_get_local (Frame *frame, gchar *name); 14 | void frame_dump_stack (Frame *frame); 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /goof.c: -------------------------------------------------------------------------------- 1 | #include "goof.h" 2 | 3 | /* c function call */ 4 | 5 | Action *call (action_func func) 6 | { 7 | Action *ret; 8 | 9 | ret = g_new0 (Action, 1); 10 | ret->do_ = func; 11 | 12 | return (Action *) ret; 13 | } 14 | 15 | /* types */ 16 | 17 | #define DEFINE_MACHINE_TYPE(goof_name, c_name, particle, gtype)\ 18 | DEFINE_TYPE(goof_name, c_name, particle, gtype)\ 19 | {\ 20 | self->value = value;\ 21 | }\ 22 | END_TYPE 23 | 24 | DEFINE_MACHINE_TYPE(boolean, gboolean, boolean, G_TYPE_BOOLEAN) 25 | DEFINE_MACHINE_TYPE(integer, gint, int, G_TYPE_INT) 26 | DEFINE_MACHINE_TYPE(real, gdouble, double, G_TYPE_DOUBLE) 27 | DEFINE_MACHINE_TYPE(big, gint64, int64, G_TYPE_INT64) 28 | DEFINE_MACHINE_TYPE(ubig, guint64, uint64, G_TYPE_UINT64) 29 | 30 | DEFINE_TYPE(str, gchar *, string, G_TYPE_STRING) 31 | { 32 | self->value = g_strdup(value); 33 | } 34 | END_TYPE 35 | 36 | /* unary operators */ 37 | 38 | ACTION(not, 39 | Action *arg; 40 | ) 41 | 42 | ACTION_IMPL(not) 43 | { 44 | GValue result = { 0 }; 45 | DO(self->arg, &result); 46 | g_value_init (ret, G_TYPE_BOOLEAN); 47 | g_value_transform (&result, ret); 48 | g_value_set_boolean (ret, ! g_value_get_boolean (ret)); 49 | } 50 | 51 | ACTION_CONSTRUCTOR(not, Action *arg, int dummy) 52 | { 53 | self->arg = arg; 54 | } 55 | END_ACTION 56 | 57 | /* binary operators */ 58 | 59 | 60 | #define INFIX_OP(gtype, particle, operator) \ 61 | case gtype:\ 62 | (g_value_set_##particle (ret, \ 63 | g_value_get_##particle (ret) \ 64 | operator g_value_get_##particle (&temp)));\ 65 | break; 66 | 67 | #define EVAL_TYPE(gtype) \ 68 | case gtype: {\ 69 | 70 | #define END_EVAL_TYPE\ 71 | }\ 72 | break; 73 | 74 | #define NUMERIC_TYPES(operator)\ 75 | INFIX_OP(G_TYPE_INT, int, operator)\ 76 | INFIX_OP(G_TYPE_DOUBLE, double, operator)\ 77 | INFIX_OP(G_TYPE_UINT64, uint64, operator)\ 78 | INFIX_OP(G_TYPE_INT64, int64, operator)\ 79 | 80 | #define BINARY_OP(name, promote)\ 81 | ACTION(name,\ 82 | Action *l;\ 83 | Action *r;\ 84 | )\ 85 | \ 86 | ACTION_IMPL(name)\ 87 | {\ 88 | GValue l = { 0 };\ 89 | GValue r = { 0 };\ 90 | GValue temp = { 0 };\ 91 | GType t, rt, lt;\ 92 | \ 93 | DO(self->l, &l);\ 94 | DO(self->r, &r);\ 95 | \ 96 | lt = G_VALUE_TYPE(&l);\ 97 | rt = G_VALUE_TYPE(&r);\ 98 | \ 99 | if ((t = promote (lt, rt)) == G_TYPE_INVALID) \ 100 | g_error ("incompatible types for operation 'plus' (%s, %s)",\ 101 | g_type_name (lt), g_type_name (rt));\ 102 | \ 103 | g_value_init (ret, t);\ 104 | g_value_init (&temp, t);\ 105 | g_value_transform (&l, ret);\ 106 | g_value_transform (&r, &temp);\ 107 | \ 108 | switch (t) { 109 | \ 110 | 111 | #define END_BINARY_OP(name) }}\ 112 | ACTION_CONSTRUCTOR(name, Action *l, Action *r, int dummy)\ 113 | {\ 114 | self->r = r;\ 115 | self->l = l;\ 116 | }\ 117 | END_ACTION 118 | 119 | static promote_arithmetic (GType l, GType r) { 120 | 121 | if ((l == G_TYPE_DOUBLE) || (r == G_TYPE_DOUBLE)) 122 | return G_TYPE_DOUBLE; 123 | 124 | if ((l == G_TYPE_INT64) || (r == G_TYPE_INT64)) 125 | return G_TYPE_INT64; 126 | 127 | if ((l == G_TYPE_UINT64) || (r == G_TYPE_UINT64)) 128 | return G_TYPE_UINT64; 129 | 130 | if ((l == G_TYPE_INT) && (r == G_TYPE_INT)) 131 | return G_TYPE_INT; 132 | } 133 | 134 | static promote_addition (GType l, GType r) { 135 | 136 | GType a; 137 | 138 | if ((a = promote_arithmetic (l, r)) != G_TYPE_INVALID) 139 | return a; 140 | 141 | if ((l == G_TYPE_STRING) && (r == G_TYPE_STRING)) 142 | return G_TYPE_STRING; 143 | 144 | return G_TYPE_INVALID; 145 | } 146 | 147 | BINARY_OP(plus, promote_addition) 148 | NUMERIC_TYPES (+) 149 | EVAL_TYPE(G_TYPE_STRING) 150 | const gchar *l, *r; 151 | l = g_value_get_string (ret); 152 | r = g_value_get_string (&temp); 153 | g_value_set_string (ret, g_strconcat (l, r, NULL)); 154 | END_EVAL_TYPE 155 | END_BINARY_OP(plus) 156 | 157 | BINARY_OP(minus, promote_arithmetic) 158 | NUMERIC_TYPES (-) 159 | END_BINARY_OP(minus) 160 | 161 | BINARY_OP(mul, promote_arithmetic) 162 | NUMERIC_TYPES (*) 163 | END_BINARY_OP(mul) 164 | 165 | BINARY_OP(div, promote_arithmetic) 166 | NUMERIC_TYPES (/) 167 | END_BINARY_OP(div) 168 | 169 | /* if */ 170 | 171 | ACTION(if_, 172 | Action *condition; 173 | Action *positive; 174 | Action *negative; 175 | ) 176 | 177 | ACTION_IMPL(if_) 178 | { 179 | GValue cond = { 0 }; 180 | GValue conv = { 0 }; 181 | 182 | DO(self->condition, &cond); 183 | 184 | g_value_init (&conv, G_TYPE_BOOLEAN); 185 | g_value_transform (&cond, &conv); 186 | 187 | if (g_value_get_boolean (&conv)) 188 | { 189 | DO(self->positive, ret); 190 | } else 191 | { 192 | DO(self->negative, ret); 193 | } 194 | } 195 | 196 | ACTION_CONSTRUCTOR(if_, Action *cond, Action *t, Action *f, int dummy) 197 | { 198 | self->condition = cond; 199 | self->positive = t; 200 | self->negative = f; 201 | } 202 | END_ACTION 203 | 204 | /* statement block */ 205 | 206 | ACTION(block, 207 | GList *actions; 208 | ) 209 | 210 | ACTION_IMPL(block) 211 | { 212 | GList *cur; 213 | for (cur = self->actions; cur; cur=cur->next) 214 | { 215 | if (G_IS_VALUE (ret)) 216 | g_value_unset (ret); 217 | DO(((Action *) cur->data), ret); 218 | } 219 | } 220 | 221 | ACTION_CONSTRUCTOR(block, int dummy, ...) 222 | { 223 | va_list l; 224 | Action *arg; 225 | va_start (l, dummy); 226 | 227 | arg = va_arg (l, Action *); 228 | while (arg) 229 | { 230 | self->actions = g_list_prepend(self->actions, arg); 231 | arg = va_arg (l, Action *); 232 | } 233 | va_end (l); 234 | 235 | self->actions = g_list_reverse (self->actions); 236 | } 237 | END_ACTION 238 | 239 | /* print statement */ 240 | ACTION(print, 241 | Action *a; 242 | ) 243 | 244 | ACTION_IMPL(print) { 245 | GValue v = { 0 }; 246 | GValue string = { 0 }; 247 | 248 | DO (self->a, &v); 249 | g_value_init (&string, G_TYPE_STRING); 250 | g_value_transform (&v, &string); 251 | g_printf ("%s\n", g_value_get_string (&string)); 252 | } 253 | 254 | ACTION_CONSTRUCTOR(print, Action *a, int dummy) 255 | { 256 | self->a = a; 257 | } 258 | END_ACTION 259 | 260 | /* vars */ 261 | 262 | ACTION(def, 263 | gchar *name; 264 | Action *expr; 265 | ) 266 | 267 | ACTION_IMPL(def) { 268 | DO(self->expr, ret); 269 | frame_set_local (vars, self->name, ret); 270 | } 271 | 272 | ACTION_CONSTRUCTOR(def, gchar *name, Action *value_expr, int dummy) 273 | { 274 | self->name = name; 275 | self->expr = value_expr; 276 | } 277 | END_ACTION 278 | 279 | ACTION(val, 280 | gchar *name;) 281 | 282 | ACTION_IMPL(val) { 283 | GValue *v; 284 | v = frame_get_value (vars, self->name); 285 | if (!v) { 286 | g_error ("value '%s' is undefined", self->name); 287 | } 288 | g_value_init (ret, G_VALUE_TYPE (v)); 289 | g_value_copy (v, ret); 290 | } 291 | 292 | ACTION_CONSTRUCTOR(val, gchar *name) 293 | { 294 | self->name = name; 295 | } 296 | END_ACTION 297 | 298 | /* function */ 299 | 300 | ACTION(function, 301 | GSList *params; 302 | Action *body; 303 | ) 304 | 305 | typedef struct { 306 | function_struct *f; 307 | Frame *vars; 308 | } closure; 309 | 310 | static closure *closure_new(function_struct *f, Frame *v){ 311 | closure *ret = g_new0 (closure, 1); 312 | ret->f = f; 313 | ret->vars = frame_new(v); 314 | 315 | return ret; 316 | } 317 | 318 | ACTION_IMPL(function) 319 | { 320 | g_value_init (ret, G_TYPE_POINTER); 321 | g_value_set_pointer (ret, closure_new (self, vars)); 322 | } 323 | 324 | ACTION_CONSTRUCTOR(function, int dummy, ...) 325 | { 326 | va_list l; 327 | gchar *arg; 328 | 329 | self->params = NULL; 330 | 331 | va_start (l, dummy); 332 | arg = va_arg (l, gchar *); 333 | while (arg) { 334 | self->params = g_slist_prepend (self->params, arg); 335 | arg = va_arg (l, gchar *); 336 | } 337 | va_end(l); 338 | 339 | /* chop the last argument, it's the body */ 340 | self->body = (Action *) self->params->data; 341 | self->params->data = NULL; 342 | /* FIXME: this leaks the first list node */ 343 | self->params = g_slist_delete_link (self->params, self->params); 344 | } 345 | END_ACTION 346 | 347 | ACTION(apply, 348 | GSList *params; 349 | Action *code;) 350 | 351 | ACTION_IMPL(apply) 352 | { 353 | GValue f = { 0 }; 354 | GSList *name, *value; 355 | Frame *frame; 356 | closure *c; 357 | function_struct *code; 358 | 359 | DO(self->code, &f); 360 | 361 | /* FIXME: notice this leaks a frame, but what are you going to do? without 362 | * ref-counting it's impossible to know when a frame can be freed. a closure 363 | * could escape and need this frame later. */ 364 | 365 | c = g_value_get_pointer (&f); 366 | code = c->f; 367 | frame = frame_new(c->vars); 368 | 369 | for (name = code->params, value = self->params; name && value; name = 370 | name->next, value = value->next) 371 | { 372 | GValue *v = g_new0(GValue, 1); 373 | DO(((Action *) value->data), v); 374 | frame_set_local (frame, name->data, v); 375 | } 376 | 377 | if (name || value) 378 | { 379 | g_error ("incorrect number of args"); 380 | } 381 | 382 | DO_WITH(code->body, ret, frame); 383 | } 384 | 385 | ACTION_CONSTRUCTOR (apply, Action *f, ...) 386 | { 387 | va_list l; 388 | Action *arg; 389 | 390 | self->code = f; 391 | 392 | va_start (l, f); 393 | arg = va_arg (l, Action *); 394 | while (arg) 395 | { 396 | self->params = g_slist_prepend (self->params, arg); 397 | arg = va_arg (l, Action *); 398 | } 399 | va_end (l); 400 | } 401 | END_ACTION 402 | -------------------------------------------------------------------------------- /goof.h: -------------------------------------------------------------------------------- 1 | #ifndef __GOOF_H__ 2 | #define __GOOF_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include "frame.h" 8 | 9 | #define ACTION_ARGS Action *self, GValue *ret, Frame *vars 10 | #define CALLBACK(name) static void name (ACTION_ARGS) 11 | 12 | typedef struct _Action Action; 13 | 14 | typedef void (*action_func) (ACTION_ARGS); 15 | 16 | struct _Action { 17 | action_func do_; 18 | }; 19 | 20 | #define DO(action, ret) action->do_(action, ret, vars) 21 | #define DO_WITH(action, ret, vars) action->do_(action, ret, vars) 22 | 23 | Action *block (int dummy, ...); 24 | Action *print (Action *value, int dummy); 25 | Action *call (action_func func); 26 | Action *def (gchar *string, Action *value_expr, int dummy); 27 | Action *val (gchar *string); 28 | Action *boolean (gboolean value); 29 | Action *integer (gint value); 30 | Action *real (gdouble value); 31 | Action *big (gint64 value); 32 | Action *ubig (guint64 value); 33 | Action *str (gchar *value); 34 | Action *object (GType type, ...); 35 | Action *function (int dummy, ...); 36 | Action *apply (Action *f, ...); 37 | Action *if_ (Action *cond, Action *t, Action *f, int dummy); 38 | 39 | Action *not (Action *f, int dummy); 40 | Action *plus (Action *r, Action *l, int dummy); 41 | Action *minus (Action *r, Action *l, int dummy); 42 | Action *mul (Action *r, Action *l, int dummy); 43 | Action *div (Action *r, Action *l, int dummy); 44 | 45 | /* useful macros */ 46 | 47 | #define id(x) #x, 48 | #define BLOCK(...) block(0, __VA_ARGS__ NULL), 49 | #define PRINT(arg) print(arg 0), 50 | #define CALL(arg) call(arg), 51 | #define DEF(...) def(__VA_ARGS__ 0), 52 | #define VAL(name) val(#name), 53 | #define BOOL(arg) boolean(arg), 54 | #define I(arg) integer(arg), 55 | #define R(arg) real(arg), 56 | #define I64(arg) big (arg), 57 | #define UI64(arg) ubig (arg), 58 | #define _(...) str(#__VA_ARGS__), 59 | #define OBJ(...) object(__VA_ARGS__ NULL), 60 | #define FUNCTION(...) function(0, __VA_ARGS__ NULL), 61 | #define APPLY(...) apply(__VA_ARGS__ NULL), 62 | #define NOT(...) not(__VA_ARGS__ 0), 63 | #define PLUS(...) plus(__VA_ARGS__ 0), 64 | #define MINUS(...) minus(__VA_ARGS__ 0), 65 | #define MUL(...) mul(__VA_ARGS__ 0), 66 | #define DIV(...) div(__VA_ARGS__ 0), 67 | #define IF(...) if_ (__VA_ARGS__ 0), 68 | 69 | #define BEGIN {\ 70 | GValue ret = { 0 };\ 71 | Frame *vars;\ 72 | Action *x;\ 73 | g_type_init ();\ 74 | vars = frame_new (NULL);\ 75 | x = block(0, 76 | 77 | #define END\ 78 | NULL);\ 79 | x->do_(x, &ret, vars);} 80 | 81 | #endif 82 | 83 | #define ACTION(name, ...)\ 84 | typedef struct {\ 85 | Action parent;\ 86 | __VA_ARGS__\ 87 | } name##_struct; 88 | 89 | #define ACTION_IMPL(name)\ 90 | static void name##_impl (name##_struct *self, GValue *ret, Frame *vars) 91 | 92 | #define ACTION_CONSTRUCTOR(name, ...)\ 93 | Action *name (__VA_ARGS__) {\ 94 | name##_struct *self;\ 95 | self = g_new0(name##_struct, 1);\ 96 | self->parent.do_ = (action_func) name##_impl;\ 97 | 98 | #define END_ACTION\ 99 | return (Action *) self;\ 100 | }\ 101 | 102 | 103 | #define DEFINE_TYPE(goof_name, c_name, gtype_particle, gtype)\ 104 | ACTION(goof_name, \ 105 | c_name value;\ 106 | )\ 107 | \ 108 | ACTION_IMPL(goof_name)\ 109 | {\ 110 | g_value_init (ret, gtype);\ 111 | g_value_set_##gtype_particle (ret, self->value);\ 112 | }\ 113 | \ 114 | ACTION_CONSTRUCTOR(goof_name, c_name value) 115 | 116 | #define END_TYPE END_ACTION 117 | 118 | -------------------------------------------------------------------------------- /simple.c: -------------------------------------------------------------------------------- 1 | #include "goof.h" 2 | 3 | CALLBACK(a_function) 4 | { 5 | g_printf ("called a c function\n"); 6 | } 7 | 8 | CALLBACK(another_function) 9 | { 10 | g_value_init (ret, G_TYPE_FLOAT); 11 | g_value_set_float (ret, 1.234); 12 | } 13 | 14 | static gchar *static_string = "foo"; 15 | 16 | int main (int argc, char **argv) { 17 | BEGIN 18 | DEF (id(foo) BOOL (TRUE)) 19 | DEF (id(bar) _(blah)) 20 | DEF (id(baz) FUNCTION (id(x) 21 | IF(VAL (x) 22 | BLOCK ( 23 | CALL (a_function) 24 | PRINT (VAL (bar)) 25 | _(x is positive) 26 | ) 27 | _(x is negative) 28 | ) 29 | ) 30 | ) 31 | 32 | // PRINT (PLUS (I(3) I(4))) 33 | 34 | DEF (id(+) FUNCTION (id(x) id(y) 35 | PLUS (VAL(x) VAL(y)))) 36 | 37 | PRINT (APPLY(VAL(+) _(abc) _(def))) 38 | PRINT (APPLY(VAL(+) I(3) R(2.4))) 39 | 40 | PRINT (MUL(MINUS (I(5) I(3)) I(4))) 41 | PRINT (MUL(MINUS (I(5) R(3)) I(4))) 42 | 43 | PRINT (_(test negation)) 44 | PRINT (NOT (BOOL (FALSE))) 45 | 46 | PRINT (APPLY(VAL(baz) VAL(foo))) 47 | PRINT (APPLY(VAL(baz) BOOL (FALSE))) 48 | PRINT (CALL (another_function)) 49 | 50 | /* test closures */ 51 | 52 | DEF (id(outer) FUNCTION(id(x) 53 | FUNCTION(id(ignored) VAL(x)))) 54 | DEF (id(one_ret) APPLY(VAL(outer) _(1))) 55 | 56 | DEF (id(two_ret) APPLY(VAL(outer) _(2))) 57 | PRINT (APPLY (VAL(one_ret) _())) 58 | PRINT (APPLY (VAL(two_ret) _())) 59 | 60 | /* do something recursive */ 61 | PRINT (_(\ncounting backward from 5\n)) 62 | 63 | DEF (id(count_backward) FUNCTION(id(x) 64 | IF(NOT(VAL(x)) 65 | PRINT (_(done)) 66 | BLOCK( 67 | PRINT (VAL(x)) 68 | APPLY(VAL(count_backward) MINUS(VAL(x) I(1))))))) 69 | 70 | APPLY(VAL(count_backward) I(5)) 71 | END 72 | } 73 | --------------------------------------------------------------------------------