writeup.tex (58579B)
1 \documentclass[a4paper,12pt]{article} 2 3 \usepackage{geometry} 4 \usepackage{titling} 5 \usepackage{titlesec} 6 \usepackage[english]{babel} 7 \usepackage[hidelinks]{hyperref} 8 \usepackage{listings} 9 \usepackage{xcolor} 10 \usepackage{graphicx} 11 \usepackage[export]{adjustbox} 12 \usepackage{forest} 13 \usepackage{tikz-qtree} 14 \usepackage{bchart} 15 16 \definecolor{codegreen}{rgb}{0,0.6,0} 17 \definecolor{codegray}{rgb}{0.5,0.5,0.5} 18 \definecolor{codepurple}{rgb}{0.58,0,0.82} 19 \definecolor{backcolour}{rgb}{0.95,0.95,0.92} 20 21 \lstdefinestyle{mystyle}{ 22 backgroundcolor=\color{backcolour}, 23 commentstyle=\color{codegreen}, 24 keywordstyle=\color{magenta}, 25 numberstyle=\tiny\color{codegray}, 26 stringstyle=\color{codepurple}, 27 basicstyle=\ttfamily\footnotesize, 28 breakatwhitespace=false, 29 breaklines=true, 30 captionpos=b, 31 keepspaces=true, 32 numbers=left, 33 numbersep=5pt, 34 showspaces=false, 35 showstringspaces=false, 36 showtabs=false, 37 tabsize=8 38 } 39 40 41 \lstset{style=mystyle} 42 43 \tikzstyle{startstop} = [rectangle, rounded corners, minimum width=3cm, minimum height=1cm,text centered, draw=black, fill=red!30] 44 \tikzstyle{io} = [trapezium, trapezium left angle=70, trapezium right angle=110, minimum width=0cm, minimum height=1cm, text centered, draw=black, fill=blue!30] 45 \tikzstyle{process} = [rectangle, minimum width=3cm, minimum height=1cm, text centered, draw=black, fill=orange!30] 46 \tikzstyle{subroutine} = [rectangle, minimum width=3cm, minimum height=1cm, text centered, draw=black, fill=yellow!30, double distance=1] 47 \tikzstyle{decision} = [diamond, minimum width=3cm, minimum height=1cm, text centered, draw=black, fill=green!30] 48 \tikzstyle{arrow} = [thick,->,>=stealth] 49 50 \titleformat{\section} 51 {\Huge} 52 {} 53 {0em} 54 {}[\titlerule] 55 \geometry{ 56 a4paper, 57 total={170mm,257mm}, 58 left=20mm, 59 right=20mm, 60 } 61 62 \author{Lucas Standen} 63 \title{The solution to bad code} 64 65 \begin{document} 66 \maketitle 67 \newpage 68 \tableofcontents 69 \newpage 70 71 \setlength{\parskip}{1em} 72 {\setlength{\parindent}{0cm} 73 74 \section{A brief head note and introduction} 75 This document has been written for the use within AQA computer science 76 Alevel coursework. It is published under the MiT license, which I hope 77 will make it of use to someone other than myself some day on the in's 78 and out's of simpler compiler design and programming languages as a 79 whole. 80 81 This is the second version of this document, it was written in GNU 82 roff before, however I decided to move over to {\LaTeX} for the 83 more modern features (notably image support). The {\LaTeX} source for 84 this document is also available along with all referenced code at 85 \url{https://git.seacrossedlovers.xyz/school}. 86 87 \section{Analysis} 88 \subsection{The current problem} 89 For general small and simple projects, I write in C. However this leads to 90 hours of debugging due to segfaults, and memory leaks. Due to the languages 91 manual memory management the programmer is required to know so much 92 information about the hardware they write for, and the second anything goes 93 wrong, it is vague on how to fix things. 94 95 \textbf{I need a language that stops me from shooting myself in the foot} 96 97 C has been standard for many decades now and its age is showing, it lacks 98 many modern features like OOP, or higher level functional abstractions, 99 that have become common in modern years due to there helpfulness. This is 100 not to fault C's achievements either, the language is my personal choice for 101 most projects for a reason, it's fast and powerful; any solution I make 102 should not cut that away. 103 104 \subsection{A solution} 105 106 \textbf{\textit{Zippy LANG}} 107 108 A next generation language, for general use. Designed for keeping code simple, 109 neat and readable. It will be similar to functional languages, known for 110 there strict ability to keep code safe and practical. The language should 111 be compiled like C/C++, Haskell and Rust for fast runtime speeds 112 113 The goal of Zippy is to make codding easier, while not limiting projects; to 114 achieve this the compiler will most likely want to use some form of middle man 115 language to achieve compatibility with more libraries. 116 117 \subsection{What is a programming language} 118 \subsubsection{A very simple explanation} 119 At its lowest definition a PL is a set of specific words, that when given 120 to a computer in the right order have a reproducible behaviour. A more human 121 way of saying that, would be "It's how we control computers". 122 \subsubsection{Why are there so many} 123 When someone is looking at code it can often be seen as just that, however 124 there are hundreds of languages that all take the idea of "code" in very 125 different ways. Some are designed for specific hardware, some are designed 126 for making general use programs while others are highly specialized. 127 It is important to see "code", as more than just one overarching term and 128 instead see where the code is being used, and evaluate it from that. 129 130 \subsection{Researching and getting a scope of the project} 131 Before I start to design a language I should first find examples of others 132 and find what I want my language to be like. I'd like my language to feel modern 133 so I should take inspiration from what other modern languages do, however on the 134 backed I want my language to be stable and fast, for that I should look at 135 older projects. 136 137 \subsubsection{Examples of older similar projects} 138 \begin{description} 139 \item[Python] 140 Python is a high level OOP language that was designed in 141 1991. It was made to make programming easy while still being able 142 to use some of C's functions. Although it has become standard for 143 many use cases, it is slow and inefficient, and very bloated. 144 145 \url{https://www.python.org/} 146 147 Zippy should take pythons high level abstractions, as they make 148 programming very easy and it should try and take notes from its 149 libraries as they are mostly well written, 150 and well documented. 151 \item[Lisp] 152 Lisp is the second ever programming language, developed at MiT, 153 and it is the first functional language, creating many common features 154 like higher order functions, recursion, and garbage collection. It is 155 generally not used any more as it feels old compared to other functional 156 languages, like Ocaml or Haskell. 157 158 \url{https://lisp-lang.org/} 159 160 Zippy should try to take a lot from the syntax of lisp, () make 161 it easy to see what parts of code will effect what, and make 162 things easy to tokenize. 163 \item[Perl] 164 Perl is scripting language designed for use in Linux, when bash is 165 too slow, or not suited for the job. Perl is often described as the glue 166 of the universe (see xkcd \url{https://3d.xkcd.com/224/}. Its syntax is 167 quite strange however and it is slow. Making it poorly suited towards 168 general use. 169 170 \url{https://www.perl.org/} 171 172 Zippy should take from perls minimalism, it is a small language that is 173 of a similar size to bash or zsh, while feeling closer to python. 174 If Zippy can achieve a similar small size, while remaining 175 powerful I will be happy with this outcome. 176 \end{description} 177 \subsubsection{Examples of newer similar projects} 178 \begin{description} 179 \item[Gleam] 180 Gleam is a modern language releasing in the past 5 years. It is 181 highly functional, with no mutable data, no traditional loops. 182 Instead recursion can be used to replace alot of these features. 183 Gleam compiles to erlang/Beam bytecode, much like java to the 184 jvm, and doing this has made Gleam a highly scalable language with 185 good library support out the box. 186 187 \url{https://gleam.run/} 188 189 Zippy should take from the functional elements of Gleam, as they keep 190 programs safer, however Zippy should not remove all procedural 191 elements, as for loops are very helpful 192 \item[Haskell] 193 Haskell is another modern functional language known for being 194 very complicated, however incredibly powerful. Its syntax feels very 195 mathematical, and incredibly terse. 196 197 \url{https://www.haskell.org/} 198 199 Perhaps Zippy could learn from Haskell, as it provides functional and 200 procedural elements, making it a well rounded language 201 \item[Hare] 202 Hare was designed to be a 100 year language, and thus stability is 203 its main goal, it is not set to 204 have a syntax change any time soon, and it has strong emphasis on 205 memory managment like C. It fits into the same part of the tech stack 206 as C, and thus it can be used for some very low level work. 207 208 \url{https://harelang.org/} 209 210 I think Zippy should have a strong emphasis on stability, much like Hare, 211 too many times have I segfaulted due to a tiny mistake. Zippy should 212 also look to Hare's small size, you can buy a copy of Hare on a 213 214 \textbf{SINGLE 3 1/2" FLOPPY} 215 216 This is something I too should try to achieve. 217 \end{description} 218 \subsubsection{What should be taken away from these languages} 219 I was already leaning towards functional programming when I started this project however 220 now I believe it's the only option for producing safe applications. Zippy will be 221 a functional language. 222 223 I also believe that I should take size of the compiler into account, as this is important 224 for keeping the project manageable and maintanable. 225 226 And finally I think that syntax should be inspired by Lisp, although Lisp itself can be 227 a messy language, with the right changes I am confident that I can make a attractive 228 language for the 21st century. 229 230 \subsection{Clients} 231 In a project of this nature, the Client is every programmer alive; which is a pretty 232 large scope. To narrow this down as much as possible, I will interview a small handful 233 of people throughout the project, of different skill levels to get a good picture of 234 what people think of the project. 235 \subsubsection{Client 1: Amy C} 236 My first client is a friend of mine, Amy C, she is a confident programmer who has 237 completed many complicated projects. I am choosing her as a client as she can give me 238 technical feed back on my project and its function/utility. 239 \subsubsection{Client 2: Myself} 240 I've wanted to take out a project like this for a long long time, and this is the 241 perfect opportunity to do so, I will be assessing myself along the way of this, 242 building the project to my personal specification. 243 244 \subsection{Questionnaires} 245 It is important to get feedback from end users, so I will take multiple questionnaires 246 throughout the project. I will then use them to slightly edit the requirements of my 247 project this should make the final outcome more helpful and what people want. 248 \subsubsection{Amy C, initial ideas} 249 \begin{description} 250 \item[What do you find the most important in a language?] 251 Speed, readability, debugging ease and disk space efficiency. 252 \item[What tools are important for a language to have?] 253 IDE integration (things like tab complete and debugging tools), a 254 package manager, and the ability to interact with the user through the 255 command line easily. 256 \item[What features do you like from other languages?] 257 The ability to pass the memory reference of an object or function and a 258 collection of built-in or standard functions like "print", "split", 259 or "sort". 260 \item[What do you want to program in this language?] 261 Lightweight command line tools and web back ends. 262 \item[Do you intend to use graphics in the programs you write?] 263 Yes. 264 \item[Would you prefer a language that focuses on ease of 265 use, or power of code?] 266 I like a good balance between the two. 267 \item[What were your last 3 projects?] 268 A website, a small command-line tool and a midi keyboard (program runs 269 on a Raspberry Pi Pico). 270 \item[How many languages would you use on a single project?] 271 I try to use as little languages in a single project as possible, so I 272 could likely not use it in an existing project. 273 \item[Do you care for low level control, or would you prefer 274 high level abstractions?] 275 I think low-level control is very important, but high-level abstractions 276 are convenient, so a good balance between the two is best. 277 \item[Would you be happy to develop libraries for things that aren't 278 already implemented?] 279 Potentially if it is simple enough to implement new things. 280 \end{description} 281 \subsubsection{Notes from questionnaire 1} 282 Some of the key things that I'm taking away from this first questionnaire, are my 283 client/users initial needs and use cases. I think it's clear my language can be of 284 assistance to my client, Zippy will be a good language for web back ends and 285 small command line tools, which my client expressed interested in. 286 287 I find the fact my client is worried by executable size interesting, however 288 I doubt it will be an issue; a ballooning code-base is unlikely as only one 289 person is writing the whole project. 290 291 I am also taking on the fact that my client wants good command line tools, 292 so a pkg-manager and bundler should be a priority, perhaps they could be 293 written in Zippy after the compiler is done. 294 295 \subsection{The first elements of the project} 296 At this stage I can say that I'm confident in my project and its scope. I 297 have a goal in mind for 298 it. 299 300 \textbf{The key things to take away from this section are:} 301 302 \begin{itemize} 303 \item 304 Make a high level language with a useable set of features, to 305 replace C in many situations. 306 307 \item 308 Keep the language readable and easy, with powerful tools available. 309 310 \item 311 Ensure the language is well supported with tools like a pkg-manager. 312 \end{itemize} 313 314 \section{Modelling} 315 In larger projects, when a programmer needs a data structure that the language 316 they are writing in doesn't provide, they will need to make their own. This can pose a 317 challenge to some, especially in low level languages which don't provide anything 318 out of the box. 319 320 Bellow are a few examples of these data structures that C doesn't already provide, 321 that I may use in my project. 322 \subsection{Linked lists} 323 this is an alternative implementation of a list, where you store some data, and 324 the memory address to the next node. Then you can move through the list by reading 325 the data then reading the data of the next node, and then repeating until the 326 'next' part of the node is empty. 327 328 A diagram showing this can be seen here: 329 330 \begin{tikzpicture} 331 \tikzset{edge from parent/.style={draw,edge from parent path={(\tikzparentnode.south)-- +(0,-8pt)-| (\tikzchildnode)}}} 332 \Tree 333 [.ll 334 [.data 335 ] 336 [.next 337 [.ll 338 [.data 339 ] 340 [.next 341 [.ll 342 [.data 343 ] 344 [.next 345 ] 346 ] 347 ] 348 ] 349 ] 350 ] 351 \end{tikzpicture} 352 353 In C this is easy to implement as you can find a memory address very easily with to 354 find where a bit of data is stored in memory (address of). I will need to use a 'struct', 355 which is a bit like a class in C (however you can't attach a function to it, nor use 356 inheritance). A simple implementation looks like this: 357 358 \begin{lstlisting}[language=C++, caption=Linked list example] 359 typedef struct ll { 360 void *data; // the data of the node 361 ll *next; // the next node 362 } ll; 363 \end{lstlisting} 364 365 The pro's of a linked list are the fact that they can have data appended to the start or 366 end easily by changing the root node, or the next node. 367 368 Linked lists have a few downsides, for example you can't move through them backwards, 369 and unless you store it on its own, you cant find the length of it in a fast way. 370 371 In my project I would like to use linked list in the AST (see later sections for info), 372 and perhaps to store lists in the language. 373 374 \subsection{Dictionaries} 375 A dictionary is a simple data structure that just stores, a bit of data, and a number or 376 string to identify it. 377 A dictionary like a linked list can be implemented with a struct in c like so: 378 \begin{lstlisting}[language=C++, caption=Dictionary example] 379 typedef struct dict { 380 void *data; 381 int id; 382 } dict; 383 \end{lstlisting} 384 385 In my project I could use this to hold variables and functions which need to be 386 checked and looked up, which is very slow when comparing entire strings, but with this 387 I can compare integer ID's which is much faster. 388 389 \subsection{Prototyping harder features} 390 \subsubsection{Abstract syntax trees (AST's) theory} 391 In a programming language many abstract data types will be used to allow the code 392 to compile and execute, however I think the hardest part of this is an abstract 393 syntax tree. This is a data structure that holds the code in an ordered form that 394 can be analysed and executed in a simple way. It is a tree structure, with the top 395 node being a root and all lower nodes being things needed to calculate the root. It can 396 be used to show mathematical expressions and function calls, but I thing easiest way to 397 show it is via a mathematical example. 398 399 Take the follow expression for example: 400 401 {\Large{\(1 + (10 * (3 - (2 * 4)))\)}} 402 403 We know that this is equal to \(-49\) 404 405 However for a computer this is far harder to understand. This is because it has no 406 understanding of order of operation. 407 408 To solve this we use an AST. 409 410 When you solve that expression you know to start with 411 \((2 * 4)\), then \(3 -\) 412 from that, following the rules of BIDMAS to solve. 413 414 We can represent the steps as a tree like so: 415 416 \begin{tikzpicture} 417 \tikzset{edge from parent/.style={draw,edge from parent path={(\tikzparentnode.south)-- +(0,-8pt)-| (\tikzchildnode)}}} 418 \Tree 419 [.+ 420 [.1 421 ] 422 [.* 423 [.10 424 ] 425 [.- 426 [.3 427 ] 428 [.* 429 [.2 430 ] 431 [.4 432 ] 433 ] 434 ] 435 ] 436 ] 437 \end{tikzpicture} 438 \\ 439 This will evaluate \(1 + (10 * (3 - (2 * 4)))\) 440 441 As you can see, you need to evaluate the expression in the most brackets 442 first, then the next, and so on, working you way up. 443 444 You can evaluate code in a similar way, treating each operation (such as +-*/) 445 as functions, doing the most deeply nested function first, then working up. 446 Each expression can be represented in this tree, then to show a whole program you 447 can create a list of trees. 448 449 \subsubsection{Abstract syntax trees (AST's) practical} 450 As a prototype i will make a program that can take mathematical expressions and evaluate 451 them, and allowing for functions (in the form f(x)). It will do this via AST's. 452 453 This prototype takes 173 lines of code, it takes a string as a cmd line argument then 454 converts it into an abstract syntax tree, and finally it executes it. This is just a 455 simple prototype and thus it is small in scope. It can only do simple operators (+-*/) 456 and requires literal values to be surrounded by [] so it knows its not another 457 expression to evaluate. 458 459 \lstinputlisting[language=C++]{../code/proto/AST/ast.c} 460 \textit{The main loop for the ast code.} 461 462 \lstinputlisting[language=C++]{../code/proto/AST/astg.c} 463 \textit{The execution loop for the ast code.} 464 465 \lstinputlisting[language=C++]{../code/proto/AST/astg.h} 466 \textit{The definition of the ast, and function prototypes.} 467 468 Above is the code for the AST, it stores an operation (which is just an integer), and 469 it stores a real left and real right value, along side two other nodes. The real values 470 are integers, this would be the 2 numbers in reference, in the expression. The 2 nodes are a 471 recursive data structure, much like putting an object of a class inside the definition of that class 472 itself. They are used to store values that may still be expressions, for example 473 (+ [1] (+ [1] [1])) the second part of this expression would be in the "right" 474 variable. 475 476 When code is executed I can check if "left", or "right" are NULL and if 477 they are I know that I am at the lowest expression that is only literal values. 478 Then I can execute that node and work my way up the tree. 479 480 The exec function will execute the operation, unless there is a deeper node, if there is 481 a deeper node, then it executes it, and places the result in the right or left spot 482 respectively. 483 484 \textbf{Here is an example input and output:} 485 486 ./ast "(+ (- [3] [1]) (- [3] [1]))" 487 488 4 489 490 {\small Note the [ ] used to tell the program where the literal values are.} 491 492 Overall this was a relatively successful prototype, however it isn't fully functional 493 as a language but it has fit the design for a prototype. 494 495 \textbf{The code for the AST can be found here: 496 \url{https://github.com/standenboy/school/tree/master/comp/lucas-standen-NEA/code/proto/ast}} 497 498 \subsection{Feedback} 499 From my first Client (Amy C), she said that putting the numbers inside square brackets 500 was inconvenient and annoying and it would be better if the numbers were separated 501 by spaces instead of separate square bracket surrounded literals. 502 503 As this is a prototype I won't fix this issue, however in the actual language this is 504 a needed feature that I will be implementing. 505 506 \subsection{Mixing linked lists and AST's} 507 Mixing these 2 data structures together you can represents an entire program. A linked 508 list of AST's is how Zippy will represent all code the user writes. To do this, use a 509 linked list, and in the data element put a AST, then the next node can contain the same. 510 This might be a help to zippy as the compiler can convert all code to an AST, then 511 compile it. 512 \section{Objectives} 513 Zippy must support the following features, it needs them to be a usable language that has 514 many uses. 515 \subsection{Core objectives} 516 \begin{description} 517 \item[1) A compiler for the Zippy language] This will have to take in Zippy code and return some other format, that can be executed. 518 \item[2) AST's used to compile source code] This means a tree like data structure is needed to process the incoming data and output it in the correct format. 519 \item[3) A lisp like syntax] This means every expression should look like a lisp S-expression, which is like so \textit{(function arg1 arg2)}. 520 \item[4) Functional paradigm language] This means the language should draw from other projects like Haskell and Common Lisp, using recursion heavily. 521 \item[5) Recursion] The language should not have any real limit to how deep recursion can go, unlike languages like python, which have a maximum depth. 522 \item[6) Higher order functions] This means functions can be passed as arguments to other functions, which is key for the language to be functional. 523 \item[7) High performance language] The language should be fast, with speeds at or better than python. 524 \item[8) A package manager] There should be a simple tool used for putting together projects and automating the compiler call. 525 \item[9) Ability to call C functions] To ensure one can actually do things in the language, they need to be able to call the existing set of C functions. 526 \end{description} 527 If possible I would like Zippy to also meet the following extra objectives. While not needed to make the project 528 usable, it will make it far nicer to work with. 529 \subsection{Extra objectives} 530 \begin{description} 531 \item[1) String parsing in the stdlib] This should be a small library that allows for comparison and modifying of strings. 532 \item[2) Graphs in the stdlib] This should be a small library that allows the user to easily make graphs and trees. 533 \item[3) Networking in the stdlib] This would be a wrapper around C-socket style networking. 534 \item[4) Graphics in the stdlib] This would be a simple front end to a library such as Raylib. 535 \end{description} 536 537 I think with these objectives in mind I will make a well rounded language that achieves my 538 goal of being used in the same way and places that C is. If all goes to plan I will 539 create a high level, compiled, functional programming language. 540 541 \section{Design} 542 \subsection{Language specification} 543 Like any other programming language Zippy needs to have a defined syntax, bellow 544 you can find a syntax for zippy that will be complaint with my objectives. 545 \subsection{Keywords} 546 \begin{description} 547 \item[defun] starts the definition of a function, will take in a name, return type, and arguments with types 548 \item[endfun] ends the definition of a function 549 \item[let] define a variable with a initial value, takes a variable name and a value 550 \item[set] change a pre defined variable, takes a variable name and a new value 551 \item[def] define a variable which doesn't have a initial value, takes a variable name 552 \item[defunptr] defines a ptr to a function same as defun, but used to pass functions as arguments 553 \item[if] starts an if block, takes a condition 554 \item[elif] starts an elif block, must come after and if block, takes a condition 555 \item[else] starts an else block, must come after an elif or if block 556 \item[endif] must be at the end of an if/elif/else block 557 \item[for] defines a for loop, takes a variable name to use as an iterator, a starting value for that variable, a condition, and a difference to change the iterator by each loop 558 \item[endfor] ends a for block 559 \item[symbol] defines a function for semantic purposes from an external executable, take a name and arguments, the symbol must be in a linked binary 560 \item[+] addition, takes 2 arguments 561 \item[-] subtraction, takes 2 arguments 562 \item[*] multiplication, takes 2 arguments 563 \item[/] division, takes 2 arguments 564 \item[=] equality comparison operation, takes 2 arguments 565 \item[!=] negative equality operation, takes 2 arguments 566 \item[\(<\)] less than equality operation, takes 2 arguments 567 \item[\(>\)] greater than equality operation, takes 2 arguments 568 \item[\(<=\)] less than or equal operation, takes 2 arguments 569 \item[\(>=\)] greater than or equal operation, takes 2 arguments 570 \item[exit] exits the program, takes a value to exit on 571 \item[return] returns from a function, and takes a value to return 572 \item[alloc] allocates a block of memory, takes a size in bytes 573 \item[struct] defines a struct, takes a name as an argument 574 \item[endstruct] ends the definition of a struct 575 \item[sizeof] returns the size of a given type, takes the type name as an argument 576 \end{description} 577 \subsection{Other code elements} 578 As one can see from the list of keywords, all blocks such as functions are defined and ended. This leads to a nice 579 form of code that isn't reliant on indentation, where blocks can be easily seen. I have made sure to keep the 580 language uniform, so function, struts, if statements and for loops all use this syntax. 581 582 Comments can be written in zippy by prefacing a line with a '/'. 583 584 All code must have a main function, if it doesn't the linker will fail. This is the entry point to the program, so 585 it is where code will start executing from. 586 587 Reverse Polish notation is used for mathematical and comparison operations, so \((2 + (4 + 3))\) would be written 588 as \((+\; 2\; (+\; 4\; 3))\). 589 \subsection{Memory management} 590 In zippy memory is semi manual to manage, like in C the programmer needs to allocate blocks of a large enough size, 591 however they do not need to free the memory, as all allocs will be freed just before a function returns. This means 592 that memory has a life time of the function it was defined in. One should note that this means that if an allocated 593 block needs to be returned, the caller function needs to allocate the block, or else the memory returned will be 594 freed as soon as the function has finished. 595 \subsection{The steps in compiling a zippy program} 596 All the programmer should need to do is call the "zpy" command, and then the code will be converted from zippy to 597 binary. However on the back end of the project, more has to happen. First the zippy code gets converted to C, this 598 is how zippy will be cross compatible with C, then the C code is compiled to ASM, then the ASM, is converted to 599 binary, and finally the linker will convert the binary into an executable, and add any libraries that are used. 600 601 For my project I will only need to do the first step, and slightly edit the second step, as C compilers, assemblers 602 and linkers already exist. So I don't need to reinvent the wheel. 603 \subsubsection{Converting zippy to C} 604 The process of converting zippy to C is yet again another long one. It starts with reading in the program, 605 then converting that into individual expressions (in zippy one expression takes up one line), then the expression 606 is converted to a data structure that holds a function name, and its arguments in individual variables and finally 607 it converts that data structure to C code via substituting names, functions, and literal values into template C code. 608 \subsection{Actually using zippy} 609 For the programmer to use zippy they must be able to call it as a command, on a text file containing their code and 610 they must give an output file name, to place the binary. To call the command, it can be simply done using the command 611 line with the "zpy" command, which the user will need to install, this is the compiler. 612 613 The compiler will have the following options to tweak the output. 614 All options are prefixed with a '-', to denote that they are not the input file. 615 616 \begin{description} 617 \item{o} - changes the output file location 618 \item{i} - tells the C compiler to include a library that is given after this argument 619 \item{c} - tells the zippy compiler to return C code instead of a compiled binary, 620 this is helpful when using zippy to make small functions in a C/C++ code 621 base 622 \item{f} - pass a flag to the C compiler, the next option should be an argument 623 accepted by gcc. 624 \end{description} 625 626 The programmer will also have access to "zpypkg" which will automatically setup their project with compile commands 627 and a template executable. It will be a very simple tool, that copies needed files around to the correct folders, 628 it will be written using Bash, (the main scripting language used by unix, along with sh and perl). It will have the 629 following arguments to allow the programmer to quickly write zippy code. 630 631 \begin{description} 632 \item[init] this will initialize the package manager, creating the needed files. 633 \item[advinit] this is an advanced form of init, it will set things up to have interoperability with C. 634 \item[build] this command can be used from within a zippy project directory, and will build the project into an executable. 635 \item[run] this will build the project, and run the newly built executable. 636 \item[clean] this will remove all temp files and binaries from the project folder, this is helpful when sharing code. 637 \item[remove] this will remove zpypkg from the current directory (think of it like a de-init). 638 \end{description} 639 640 \subsection{Modelling the compilation process} 641 \begin{tikzpicture}[node distance=2cm] 642 \node (start) [startstop] {Start}; 643 644 \node (in1) [io, below of=start] {Read in command line arguments}; 645 \node (proc1) [process, below of=in1] {Set global variables based on command line arguments}; 646 \node (in2) [io, below of=proc1] {Read input file into an array of strings}; 647 \node (proc2) [process, below of=in2] {Convert line to an AST containing relevant info}; 648 \node (proc3) [process, below of=proc2] {Convert AST into C code}; 649 \node (out1) [io, below of=proc3] {Output C code to file}; 650 \node (dec1) [decision, below of=out1, yshift=-1cm] {Is end of file?}; 651 \node (proc4) [io, right of=dec1, xshift=6cm] {Load next line for processing}; 652 \node (out2) [io, below of=dec1, yshift=-1cm] {Use C compiler on output file}; 653 654 \node (end) [startstop, below of=out2] {End}; 655 656 \draw [arrow] (start) -- (in1); 657 \draw [arrow] (in1) -- (proc1); 658 \draw [arrow] (proc1) -- (in2); 659 \draw [arrow] (in2) -- (proc2); 660 \draw [arrow] (proc2) -- (proc3); 661 \draw [arrow] (proc3) -- (out1); 662 \draw [arrow] (out1) -- (dec1); 663 \draw [arrow] (dec1) -- node[anchor=east] {Yes} (out2); 664 \draw [arrow] (out2) -- (end); 665 \draw [arrow] (dec1) -- node[anchor=north] {No} (proc4); 666 \draw [arrow] (proc4) |- (proc2); 667 \end{tikzpicture} 668 This is a high level diagram of what will go on in my code, with each box corresponding to around 1 function. 669 670 \subsection{Modelling data structures I will use} 671 \subsubsection{AstNode} 672 \begin{tikzpicture} 673 \tikzset{edge from parent/.style={draw,edge from parent path={(\tikzparentnode.south)-- +(0,-8pt)-| (\tikzchildnode)}}} 674 \Tree 675 [.astNode 676 [.function 677 ] 678 [.arguments[8] 679 ] 680 [.children[8] 681 [.function 682 ] 683 [.arguments[8] 684 ] 685 [.children[8] 686 [.function 687 ] 688 [.arguments[8] 689 ] 690 [.children[8] 691 [.... 692 ] 693 ] 694 ] 695 ] 696 ] 697 \end{tikzpicture} 698 \\ 699 This is the main data structure that powers the compiler, it takes a fuction name as a string, an array of 8 arguments as 700 strings, and an array of 8 children as astNodes. The fuction argument will be the first word of a line of Zippy, it is the 701 name of the function. The argument variables are each litteral argument, such as a string or integer litteral that is given 702 to the fuction, this can be empty. The children argument contain more astNode, they are arguments that are given in the 703 form of functions, for example (printint (+ 2 2)), would result in (+ 2 2) having its own astNode made, and put as the child 704 of the (printint) astNode. 705 706 \subsubsection{Array list} 707 \begin{tikzpicture} 708 \tikzset{edge from parent/.style={draw,edge from parent path={(\tikzparentnode.south)-- +(0,-8pt)-| (\tikzchildnode)}}} 709 \Tree 710 [.arrayList 711 [.data[length] 712 ] 713 [.length 714 ] 715 ] 716 \end{tikzpicture} 717 \\ 718 This is a far simpler data structure, it is useful in languages such as C, C++ and rust to represent non fixed length 719 arrays. This is because in these languages arrays are stored as continous bytes in memory, making it hard to tell where 720 they end. An array list is a data structure that store the array with an interger value of the length, thus making it 721 so one knows how long the list is. This is important to avoid runtime errors such as segmentation faults, caused by 722 reading out of bounds memory. 723 724 \subsection{Why so few?} 725 It was an intentional choice to uses so few data structures, in languages like C, where OOP is not possible, 726 the importance of bundling data is far smaller, with arrays and variables being far more useful than anything 727 else; they have faster runtime speeds and a cleaner syntax that makes them preferable. One will find alot of 728 C projects will follow this phylosophy, as it generally leads to better projects. 729 730 \section{Implementation} 731 \subsection{Main C code} 732 As has been previously mentioned, zippy will have its compiler written in C and its package manager writen in bash. 733 The code will be displayed bellow, it has been commented to use a tool I wrote called autodoc, which can function 734 like a doc-string in python, after each file I will explain in detail what it does and why it is in its own file. 735 736 \lstinputlisting[language=C++]{../code2/zpy.c} 737 \textit{zpy.c} 738 739 This is the main executable, containing my main function, which is the program entry point. This file handles the 740 opening of input and output files, calling other functions, and processing the command line arguments. 741 \lstinputlisting[language=C++]{../code2/fileread.c} 742 \textit{fileread.c} 743 744 This file is responsible for reading in the file contents, into and array list of strings (an array list is an array 745 with a length attached to it, to help with memory managemnt). This file also handles the stripping of tabs and other 746 forms of white space. 747 748 \lstinputlisting[language=C++]{../code2/tokenizer.c} 749 \textit{tokenizer.c} 750 751 This file has the job of converting a single line of code into An abstract syntax tree, it splits each expression into 752 its function name, as a string, and each of its arguments (max 8) as a string, and if there are nested function calls, 753 it will create more AST nodes for them, in the recursive data structure. The main tokenizer function is using 754 a lesser known feature of the C programming language, \textit{goto}, it uses this to achieve recursion, without needing 755 to define a second function, as goto lets the user define a label in their code, just like in ASM. 756 757 \lstinputlisting[language=C++]{../code2/appendsnprintf.c} 758 \textit{appendsnprintf.c} 759 760 This is a smaller file, that defines a helper function used heavily in the comp.c file, this function allows the user 761 to concatenate an unknown amount of strings together. It uses another lesser known feature of C, \textit{vardic functions}, 762 which allow the program to parse an unknown amount of arguments to a function. This function is needed, as C does not 763 provide an effective way to concatenate strings multiple times, the function that this is built off \textit{snprintf} can only be used 764 once per variable, which didn't fit my use case. 765 766 \lstinputlisting[language=C++]{../code2/comp.c} 767 \textit{comp.c} 768 769 This file is by far the largest and most important in the program, it converts a zpy AST to C code, and writes it to an output 770 file. It also handles syntax errors in the users code. The first function from this file that is called, is the CompilerInit, 771 this sets up an interrupt which is used to jump the program to a different point, if there is a syntax error. 772 773 The next function from this file that is called, is the main Compile function, this is actually a wrapper around the compile function. 774 This function is used to set the current line, which is used if there is an error, call the main compile function, write to 775 the output file and add newlines, if needed. And finally it handles the automatic free function of zippy. 776 777 The main function that this provides is the compile function, this starts by processing child arguments, A child argument can be created 778 by the tokeniser when a nest function is used in zpy, for example (let a:int (+ 2 2)), in this case the child function is (+ 2 2). It 779 will compile the children function first, using the processChildren function, assigning their outputs to the argument section of the AST. 780 It then uses a large if block, to determine which function it is needing to generate. Each branch, use the appendsnprintf function to 781 combine the arguments and templated C code. The checkNULL function is used a lot in this function. This is because if the user does 782 not provide enough arguments to a function call, which is the most common syntax error after a missing bracket, the argument slot, will 783 be null, thus I can check if it is NULL, to tell if the user made an error. If an error is made a signal is sent to the process, which 784 will cause the interrupt handler function to be triggered, telling the user the line number they made the error on with a brief description 785 of the issue. 786 787 Also in this file are a handful of helper functions in the conversion process, these convert zippy's reverse polish notation to traditional 788 infix definition, and convert Zippy's type annotations to C's type annotations. 789 790 Finally, as previously mention there is the errorhandle function. This is triggered by a signal being sent to the program, and will cause 791 it to stop instantly, and will trigger an error print. 792 793 \lstinputlisting[language=C++]{../code2/util.c} 794 \textit{util.c} 795 796 This file defines a smaller helper function, which is used in the main executable to gracefully exit if there is an error. 797 798 \subsection{Header files} 799 \lstinputlisting[language=C++]{../code2/fileread.h} 800 \textit{fileread.h} 801 \lstinputlisting[language=C++]{../code2/tokenizer.h} 802 \textit{tokenizer.h} 803 \lstinputlisting[language=C++]{../code2/comp.h} 804 \textit{comp.h} 805 \lstinputlisting[language=C++]{../code2/appendsnprintf.h} 806 \textit{appendsnprintf.h} 807 \lstinputlisting[language=C++]{../code2/util.h} 808 \textit{util.h} 809 810 These files are used internally to allow for the linking of C code to function properly; see the following section for 811 more info on the C linking process. 812 813 \subsection{The C linking process} 814 When one writes C code, it is first compiled by a compiler, in most cases this is a compiler like GCC, or clang. 815 These will convert the C code into ASM, (sometimes through a middle man language to make compiling for many systems 816 easier), which then gets assembled into an object file. These object files are not executable, in this state they 817 are libraries that can be used in other code. To make them executable they must be linked with the C stdlib and any 818 other used binary files; this is done by the linker. The linker will take the list of symbols defined in the object file, 819 each symbol will correspond to one function in C. It will also take all the symbols in the libraries that the code is linked 820 with. This means common libraries only need to be compiled once, and the linker can take pre compiled binaries and use them. 821 822 In this project, each .c file is converted to a .o file (an object file), and then the linker will link all of them together 823 to produce the final executable. 824 825 To automate the process of compiling and linking, I've used a make file, a build tool which can have multiple functions defined 826 that will compile all the given code. Here is makefile: 827 828 \lstinputlisting[language=C++]{../code2/Makefile} 829 830 This may look confusing, however its goal is very simple, each label (which are denoted with a ':') is a function 831 that can be run, the 'all' function is an omni function ran when the user types in 'make' with no arguments, whereas the others 832 can be called with 'make install' and 'make clean'. The .c.o label is special, it compiles every C file, into a .o file, this is a 833 shorthand syntax, that isn't very readable, but is easy to use. The .PHONY function is another special option, this is used to ensure 834 autocomplete works in the terminal when typing the make commands. Finally the variables defined at the top, are used to define compiler 835 options. In this case, im using -O3, which tells the compiler to perform the maximum optimisations to my code. Ensuring the compiler is 836 fast. 837 838 \subsection{Zpypkg} 839 To make the package manager, I will be using bash to generate simple build scripts and default files. The tool doesn't need to do too 840 much it just needs to make it easier to initialize a project. It will not use networking in any way, instead, it will leave it up 841 to the programmer, so they can use any protocol or tool they like, such as git. 842 843 The code for zpypkg can be seen below. 844 \lstinputlisting[language=Bash]{../code2/zpypkg/zpypkg.sh} 845 \textit{zpypkg.sh} 846 847 This code is very simple, it can create a default main.zpy file and a zpybuild.sh file that can be used to compile a zpy project 848 in one instruction. It also has build and run functions to allow the developer to quickly produce and run up to date binaries. 849 850 \subsection{Zpylib} 851 The language needs a simple standard library that will handle the simple IO functions, this is by no means perfect but it is a 852 good enough base, that it can be easily extended to a full project. 853 \lstinputlisting[language=C++]{../code2/stdlib/zpylib.c} 854 \textit{zpylib.c} 855 856 These functions for the most part are a wrapper around the c stdlib, which is what makes them such a good base to use. 857 858 \lstinputlisting[language=C++]{../code2/stdlib/String/String.c} 859 \textit{String.c} 860 861 These functions will create a simple object oriented style development for the use of strings, allowing the user to split, create, 862 destroy and insert into strings. This library allows the user to easily make parsers and other such string related tools. 863 864 \subsection{Other libraries} 865 While I haven't ported or made any other libraries for zpy, this doesn't mean they can't be used, as long as a library can be linked 866 with C code (see the linking section above for more info), it can be used within zpy, and any function in the C stdlib is already 867 available to use. I will use this later in my examples to use the Raylib graphics library. 868 869 \section{Testing} 870 \subsection{Introduction} 871 To test zpy, I have made a few sections of example code, to test that the compiler can indeed convert code to C. I decided I would 872 test the following 873 \begin{description} 874 \item[Recursive Fibonacci program] A simple program that will calculate the n'th Fibonacci number 875 \item[String splitting] A small program that splits a string, to test the string processing class 876 \item[A incorrect program] To test the languages error messages 877 \item[A hello world program using zpypkg] To test that zpypkg can be used to manage projects 878 \item[Space invaders] Using the Raylib graphics library, I will build a clone of space invaders 879 \end{description} 880 \subsection{Fibonacci} 881 The N'th number in the Fibonacci sequence can be calculated by adding the previous 2 numbers in the sequence, and assuming the first 882 2 numbers are both 1. 883 884 For example here is the first few digits: 885 886 \(1, 1, 2, 3, 5, 8, 13, 21\) 887 888 \subsubsection{Code} 889 In zpy this code can be written as follows: 890 891 \lstinputlisting[language=lisp]{./examples/fib/zpy/fib.zpy} 892 \textit{fib\_example.zpy} 893 894 A simple explanation of what is happening in this code is, 895 896 \begin{description} 897 \item[] I make a function called fib, that returns an int, and takes an int called \(n\) in as input 898 \item[] I create a base case using the if statement, comparing if \(n < 2\) 899 \item[] I return the value of \(n\) if it is less than 2 900 \item[] Otherwise I return the sum of the previous to values in the sequence 901 902 \item[] I then define a main function that is marked as returning an int, this is where execution of the 903 program begins 904 \item[] I prompt the user for an input and read it in as an integer 905 \item[] I perform the fib calculation and print the value 906 \end{description} 907 908 \subsubsection{Examples in other languages} 909 The following python code produces the same output 910 911 \lstinputlisting[language=python]{./examples/fib/python/fib.py} 912 \textit{fib.py} 913 914 The following haskell code produces the same output 915 916 \lstinputlisting[language=haskell]{./examples/fib/haskell/app/Main.hs} 917 \textit{fib.hs} 918 919 The following java code produces the same output 920 921 \lstinputlisting[language=java]{./examples/fib/java/fib.java} 922 \textit{fib.java} 923 924 The following go code produces the same output 925 926 \lstinputlisting[language=go]{./examples/fib/go/fib.go} 927 \textit{fib.go} 928 929 The following C++ code produces the same output 930 931 \lstinputlisting[language=C++]{./examples/fib/c++/fib.cpp} 932 \textit{fib.cpp} 933 934 The following rust produces the same output 935 936 \lstinputlisting[language=go]{./examples/fib/rust/fib.rs} 937 \textit{fib.rs} 938 939 \subsubsection{Performance} 940 The zippy code is orders of magnitude faster than the python code, the time command in Unix can be used to show this. 941 942 \begin{center} 943 \small{\textit{A table comparing the performance of zippy and python, when finding the 30'th Fibonacci number.}} 944 \end{center} 945 \begin{center} 946 \begin{bchart}[max=0.4] 947 \bcbar[label=Zippy, color=yellow]{0.02} 948 \smallskip 949 \bcbar[label=Python, color=blue]{0.339} 950 \smallskip 951 \bcxlabel{time in seconds \textit{lower is better}} 952 \end{bchart} 953 \end{center} 954 955 \subsection{String splitting} 956 \subsubsection{Code} 957 The following code is a simple example of string splitting in zpy, using the standard library. All it does 958 is split the string hello\_world into the substrings of hello and world, using the \_ as a delimiter. 959 \lstinputlisting[language=lisp]{./examples/str_example.zpy} 960 \textit{str\_example.zpy} 961 962 The code is in 3 main sections: 963 \begin{description} 964 \item[] Defining the starting string 965 \item[] Splitting the string 966 \item[] Cleaning up the memory 967 \end{description} 968 \subsubsection{Output} 969 \lstinputlisting{./examples/string.example} 970 \subsubsection{Explaining} 971 The cleaning of the memory isn't strictly needed in this situation, as it will be freed automatically when 972 the program ends. As Zippy is closely related to C, this is still a needed feature for the program to be 973 safe, however code written in Zippy has some extra safety features, such as auto freeing of memory when 974 a function finishes. However as that feature only works on memory allocated with \((alloc)\), freeing must be done 975 manually for other things, such as the string library. 976 977 \subsection{zpypkg example} 978 To use zpypkg I wanted it to be very easy, and hassle free. Other packaging tools like cargo, require entire 979 projects to be built with them in mind, this forces a specific project structure that isn't tuned to all use 980 cases. I believe that \(Go\) hits the mark on a good packaging tool, it is clean, small and out of the way, 981 simply providing automated builds and running of the code. 982 \subsubsection{Using zpypkg} 983 \lstinputlisting[language=bash]{./examples/zpypkg.example} 984 Its as simple as that! Out of the way, and customizable via the build.sh file that zpypkg generates. 985 986 \subsection{Space invaders} 987 \subsubsection{Background} 988 To build a small space invaders game, I'm going to use the Raylib graphics library 989 (\url{https://www.Raylib.com/}) 990 based on GLFW. It is well known and over 10 years old at this point, it is fast, supports most devices and 991 operating systems under the sun, and is written in C for C, and due to this, it is also compatible with Zippy! 992 \subsubsection{Code} 993 \lstinputlisting[language=lisp]{./examples/spaceinvaders.zpy} 994 \textit{spaceinvaders.zpy} 995 996 While this may look like a large amount of code, it is actually quite simple, it opens a window, starts a loop, if 997 the player shoots the alien it takes damage, if the alien has taken enough damage the game ends, and if the alien 998 reaches the ground the player loses. For simplicity's sake, the program uses exit codes to establish what the outcome 999 of the game was, this can be checked on a Unix like system like so: echo \$?. For this game, if this returns a 0, the 1000 player has one, otherwise the alien enemy has won 1001 \subsubsection{Seeing it go} 1002 Bellow is a screenshot of the game working, its graphics are minimal to say the least, but it does prove Zippy can be 1003 used with C libraries. 1004 1005 \includegraphics[width=\textwidth, left]{./examples/spaceinvaders.png} 1006 \textit{The player is green, The alien is red} 1007 1008 \section{Evaluation} 1009 At this stage in my project, I have created a full project, and now I need to compare it to my original goals. 1010 1011 Here is a copy of my original goals to avoid needing to flick between many pages. 1012 \subsection{Core objectives} 1013 \begin{description} 1014 \item[1) A compiler for the Zippy language] 1015 \item[2) AST's used to compile source code] 1016 \item[3) A lisp like syntax] 1017 \item[4) Functional paradigm language] 1018 \item[5) Recursion] 1019 \item[6) Higher order functions] 1020 \item[7) High performance language] 1021 \item[8) A package manager] 1022 \item[9) Ability to call C functions] 1023 \end{description} 1024 \subsection{Extra objectives} 1025 \begin{description} 1026 \item[1) String parsing in the stdlib] 1027 \item[2) Graphs in the stdlib] 1028 \item[3) Networking in the stdlib] 1029 \item[4) Graphics in the stdlib] 1030 \end{description} 1031 1032 \subsection{Comparing the goals to the product} 1033 In order I will evaluate and show where and how these came to be in my final code. 1034 1035 \subsubsection{A compiler for the Zippy language} 1036 This was the main goal of the project and I achieved this perfectly as planned, the compiler generates C code that runs 1037 quickly and efficiently with extra safety features. This is a language that is less dangerous that C, while keeping the 1038 same performance. 1039 1040 This goal was fully met. 1041 1042 \subsubsection{AST's used to compile source code} 1043 This was a goal for the internal design of the project, and I achieved this too with my ast\_node tree data structure, 1044 it made the rest of the compilation process far easier as there was less worry for passing data around in random ways. 1045 1046 This goal was fully met. 1047 1048 This can be seen here: 1049 \begin{lstlisting}[language=C++, caption=AST definition] 1050 typedef struct astNode { 1051 char *func; 1052 char *args[8]; 1053 struct astNode *children[8]; 1054 } astNode; 1055 \end{lstlisting} 1056 1057 1058 \subsubsection{A lisp like syntax} 1059 This goal was also met thanks to the advanced tokeniser I wrote that is capable of generating AST's from individual lines 1060 of Zippy, you can see this first hand when you look at the use of parentheses in the language. 1061 1062 This goal was fully met. 1063 1064 \subsubsection{Functional paradigm language} 1065 This goal is more up to argument, as to weather I achieved it or not. The language definitely has many features from functional 1066 programming, however none of them are enforced, making it harder to achieve the benefits. In terms of paradigm I feel Zippy 1067 fell closer to imperative, but one should note Zippy does support all major functional features, such as higher order functions and 1068 recursion. Functional programming really shows its benefits when it is used exclusively, which isn't done in zippy, however with 1069 determination, one could definitely use Zippy in the same way one uses Lisp. 1070 1071 This goal was met, however not to the fullest. 1072 1073 \subsubsection{Recursion} 1074 As zippy is dependant on C, it can support any feature C can out the box, and C is perfectly capable of using advanced recursive 1075 algorithms. 1076 1077 This goal was fully met. 1078 1079 \subsubsection{Higher order functions} 1080 To achieve this goal I created the \((defunptr)\) keyword which allows the programmer to pass a function as a pointer from within 1081 a struct or variable. I find this to be a very elegant way of implementing higher order functions, as it is very simple for 1082 low level development, which is where Zippy lies on the tech stack. 1083 1084 This goal was fully met. 1085 1086 This can be seen here: 1087 \begin{lstlisting}[language=C++, caption=Function pointer support] 1088 else if (strcmp(names[28], node->func) == 0){ // converting function pointer definition staments 1089 checkNULL(node->args[0], "expected function ptr type"); 1090 checkNULL(node->args[0], "expected function ptr name"); 1091 out = appendsnprintf(out, MAXOUTLEN, "%s (*%s)", node->args[1], node->args[0]); 1092 int i = 2; 1093 while (node->args[i] != NULL){ 1094 if (i != 2) out = appendsnprintf(out, MAXOUTLEN, ","); 1095 else out = appendsnprintf(out, MAXOUTLEN, "("); 1096 out = appendsnprintf(out, MAXOUTLEN, "%s", getVarType(node->args[i])); 1097 i++; 1098 } 1099 out = appendsnprintf(out, MAXOUTLEN, ")"); 1100 } 1101 \end{lstlisting} 1102 1103 \subsubsection{A high performance language} 1104 As it was previously seen in the examples section, zippy has been able to crush python, and for me this was enough. For most 1105 use cases python is fast enough, and thus zippy being faster means it will never be too slow. 1106 1107 This goal was fully met as seen in my comparisons against python. 1108 1109 \subsubsection{A package manager} 1110 I believe zpypkg was exactly what I wanted to make, it is small fast and too the point, it doesn't get in the programmers way 1111 like larger tools available. 1112 1113 This goal was fully met. 1114 1115 \subsubsection{Ability to call C functions} 1116 Zippy is fully able to call C functions and I even created a keyword to define prototypes for them \((symbol)\), this made 1117 it very easy to call C functions when needed, however it is not needed, as the linker is what puts in most the work to 1118 achieve this. 1119 1120 This goal was fully met. 1121 1122 \subsection{Thoughts on the core objectives} 1123 I believe that I have hit all of my core objectives well enough to define my project as complete, I have made a programming 1124 language that I would happily use for many projects, with it supporting all the features I could need. Although if I had more 1125 time there are some things I would have liked to add, notable a more full standard library, as of current Zippy is reliant 1126 on the C stdlib and many of its downsides have been passed over into Zippy. 1127 1128 \subsection{Extra objectives} 1129 While these were optional, I still took the liberty of making them to make a more achieved project. I did not complete them 1130 all due to time constraints. I made string parsing and graphics available in the standard library, via the string functions 1131 previously shown, and linking with the Raylib graphics library. 1132 1133 One could argue that all of these things are possible, as it is possible to link with a pre existing library to do the work 1134 for you, but in some ways that cheating, and also won't work for libraries written in C++. 1135 1136 \subsection{Final client response} 1137 \subsubsection{Amy c} 1138 To finally test my project I will get my client (Amy C) to use zippy for some simple tasks, and see what they thing of it. 1139 1140 \begin{description} 1141 \item[What do you like about Zippy?] 1142 One thing about Zippy that I like is the disk size efficiency. 1143 \item[What do you not like about Zippy?] 1144 I do not like the learning curve of learning to use polish notation. 1145 \item[What would you change about Zippy?] 1146 I would add syntax highlighting to editors (VSCode, micro, etc.) 1147 \item[Any other comments about Zippy?] 1148 I would have preferred if the language felt more fleshed out in some places, such as error messaging. As 1149 in the current state the language doesn't feel fully finished. 1150 \end{description} 1151 1152 \subsubsection{Response to Amy C} 1153 I overall agree with the points Amy has made, the language could have been made bigger and error messages could have been put 1154 ahead on the projects planning. I would also have liked to implement code editor integration but it was out of the scope of the 1155 project. 1156 1157 \subsubsection{Myself} 1158 As previously stated I am one of the clients for this project as I wanted to make something that I could use or extend. I feel 1159 that I have achieved this, however I'd like to remake large chunks of it into something bigger, and with hindsight I feel confident 1160 to explore the concepts I first introduced here into something larger. 1161 1162 \section{Conclusion} 1163 \subsection{What would I change if I did this again?} 1164 If I was given the opportunity to remake Zippy I would like a few things different. Firstly, I wish I had thought of how 1165 I was going to implement error messages earlier on in the process, as they felt rather slapped on the side, and didn't give 1166 messages in a verbose enough manner. Secondly, I would have liked it if the language drew less on C functions when being used; 1167 the point of the languages was to be higher level than C, and while it was in some aspects, some rather missed the mark. Finally 1168 I would have liked to have made the AST's that power the compiler to rely less on strings and more on nested data structures; 1169 I found the compiler became messy in the code generation section as it was a lot of string parsing which should have been done 1170 in earlier steps in the compilation process. 1171 \subsection{Final thoughts} 1172 Overall I believe this project has achieved its goals nicely, I have made a simple language that has the power of C and 1173 the syntax of lisp, with added memory safety; this is what I set out to do. Along this project many things changed, from 1174 the scope of the language to the style it would take. When this project first started it was going to be a fully lisp 1175 like language with its own interpreter (not compiler), and was going to focus on higher level concepts that the final 1176 product. I decided to rewrite the code, and this write-up due to a ballooning code base and lack of features, the code 1177 was becoming impossible to manage and I had learned better ways of implementing features that what was originally used. 1178 When I began the re-write of the code, I thought it wise to re-write this write-up as my goals had changed, I also wanted 1179 to move it from GROFF MS to {\LaTeX} as GROFF had been giving challenges with including code segments. 1180 1181 While if I had more time available I would like to flesh this out more, with features like text editor integration, and 1182 a nicer standard library, I believe I took this project to a good state. 1183 } 1184 \end{document} 1185