| Commit message (Collapse) | Author | Age | Files | Lines |
| ... | |
| | |
|
| |
|
|
|
|
|
|
|
|
| |
This was possible, but very tedious to do by hand before. Now we
automate it based on the number of arguments.
Note that currently we can't just add `syscall3()` etc as builtins
because the actual numbers for the system calls vary from one system
to another, and we want to maintain support for macOS and Linux (at
least for now).
|
| |
|
|
| |
Since we allow implicit conversions now the exact type is less relevant.
|
| |
|
|
|
| |
`putc`, `puts`, and `putnum` in `std/common.cup` are now implemented
in terms of the `write()` syscall.
|
| |
|
|
|
| |
Probably want to add more builtins in the future, so pulling it out
of `parser.c` seems like the reasonable thing to do
|
| |
|
|
| |
This design should also be useful for structs down the road.
|
| |
|
|
|
|
| |
In the future we can split this into multiple files if we need to,
after we've added to ability to handle more complex input graphs without
parsing the same file twice.
|
| |
|
|
| |
Simple optimization, it was just adding extra overhead anyway.
|
| |
|
|
|
|
|
|
|
|
|
| |
This commit does a few things in one go:
- Add support for a `char` type + some changes to support the new size
- Add support for character literals. We need some escaping here to be
able to use `\n` and `\0`, etc.
- Add support for string literals. These are all stored in the `.data`
section. Fortunately NASM already handles the escape characters.
- Fix some bugs with code generation, specifically using `movsx` to sign
extend the smaller types into 64-bit registers.
|
| |
|
|
|
|
| |
This made sense when all variables were of the same size, but now
with arrays we don't initialize them by default. Perhaps we should
find a way to 0-initialize all the memory?
|
| | |
|
| |
|
|
|
|
| |
Usual disclaimer at this point: Quick&Dirty implementation, hasn't
been tested other than basic sanity checks. Arrays are automatically
decayed into pointers when the identifier is accessed.
|
| |
|
|
|
|
| |
It was getting a bit unwieldy in `parser.c`, and this will potentially
help when we start dealing with more complex type-stuff such as
casting / conversions / etc.
|
| |
|
|
| |
With the fancy new type checking these are now required.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This is a bit of a chonky commit, but it adds in the basics of checking
the types of expressions / function calls / return types. There's still
a lot of work to be done, including:
(1) Adding new core types, and casting between allowed types
automatically
(2) Picking the corrent output type based on input types (for instance
float+int == float)
(3) We need much better error reporting, the error messages are really
vague and unhelpful as-is
(4) We also need to work to ensure that a function with a return type
actually returns
(5) Possible re-factoring to make stuff less hacky when we have more
types / structs / arrays / etc.
|
| |
|
|
|
|
| |
While I prefer the latter, the lexer/parser cannot correctly parse
`type&&` since it thinks `&&` is `TOKEN_AND`. Perhaps how these cases
are handled can be changed in the future.
|
| |
|
|
|
|
|
|
|
|
| |
This commit adds initial support for taking pointers / dereferencing.
The type system is still a bit of a hot mess, so all type information
is actually not looked at, but the functionality still seems to be
there.
Still need to add some tests for pointers/dereferencing to ensure that
it works in some edge cases as well.
|
| |
|
|
| |
This will make it trivial to compute pointers!
|
| | |
|
| |
|
|
|
|
|
| |
We now dynamically allocate the type structure, and recursively
store a reference to the original type if it's a pointer. For now it's
a little bit of a waste but it helps us future-proof stuff for more
complex things to come
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
We restore the count later, but this fix makes it so that the compiler
doesn't get stuck in an infinite loop when you try to compile the
following code:
```
fn main(): int {
defer return 5;
return 1;
}
```
|
| |
|
|
|
|
| |
We don't have any closures yet, so it's essentially the same as just
moving the statement after the `defer` keyword to the end of the block/
right before returning from the function.
|
| | |
|
| |
|
|
|
|
| |
Previously we weren't creating a new assignment node, and this was
causing all sorts of funky errors. This commit also fixes that, and
we can now use global variables :^)
|
| | |
|
| | |
|
| |
|
|
|
| |
We now also test for local variables in functions, and add a simple
test to see if imports work properly.
|
| |
|
|
| |
For now this is very limited, but shows the ability to import files!
|
| |
|
|
|
|
| |
This still requires a lot of work to avoid duplicate imports, and
handle cyclic imports, but it is a good enough for small examples
which just want to include some common definitions from std/
|
| |
|
|
|
|
|
| |
(1) Prefix function names with `func_` now, to avoid clasing with
possible NASM keywords (such as `abs`).
(2) Label numbers are now properly handed for conditional expressions.
|
| |
|
|
|
|
| |
The stack actually grows downwards, so we need to account for that.
The previous implementation was incorrect and exploded if you tried
to use local variables in other functions except main.
|
| | |
|
| |
|
|
|
|
|
| |
This isn't really super extendible for now, but it's a start and gives
us the `print` builtin which allows us to finally actually print out
values to the screen, so we can move away from testing with exit codes
eventually.
|
| | |
|
| |
|
|
|
|
|
|
|
| |
`make` to compile the compiler
`make XXX.out` to assemble/link `XXX.nasm` into an executable
`make test` to run all tests
`make tests/XXX` to run `tests/XXX.sh` test file
`./run.sh <cupcc args>` to build, compile, run and show exit code
|
| | |
|
| |
|
|
|
| |
The language has progressed enough now to the point where that doesn't
do anything meaningful anymore.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
We now support function calls! We don't have support for forward
declaring functions right now though, so no mutual recursion is
possible.
The arguments are passed via the stack instead of through registers
(unlike the x86_64 calling convention, I think). We'll probably need
some sort of primitives built into the language for syscalls
eventually because of this.
Return types are also not checked, and right now it's possible to have
a function that doesn't return anything even when the caller expects it
to, error checking and reporting definitely needs to be improved.
|
| | |
|
| |
|
|
|
|
| |
We can now loop and do stuff, yay! However, we don't yet allow
declarations inside the for-loop initializer, since that is a bit
more annoying to implement.
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| |
|
|
|
|
|
|
|
| |
We now support OR and AND with short circuiting! (Yet to be tested
since we don't yet have local variables to play with).
The binop parser took a bit of an overhaul factoring out the common
code so that it's easier to describe the operator precendence
relationships without being overly repetitive.
|