Open ghost opened 4 years ago
@IsaacShelton Where the program for detecting this warnings and errors in binaries placed in the Adept source code? (I just want to understand how it works)
@t0md3an It's built into the same executable, adept
. They're scattered throughout the codebase, because they get triggered by a variety things. Most of them are calls to compiler_warn
or compiler_warnf
(defined in src/DRVR/compiler.c
), and a few are to yellowprintf
(defined in include/UTIL/color.h
).
@IsaacShelton How this is works:
I can’t find I code vsprintf()
function, I just want to understand how this detector works:
$ ./file
WARNING: vsprintf(*String, String, VariadicArray) expected *ubyte value for %s, got 'int' instead
zsh: segmentation fault ./file
Ah, I understood, this is a 2.4/parse.adept
showing this warning.
@IsaacShelton Is #place/print_warning
stopping program execution? If not, I think user will’ll not want to saw this warnings at every binary execution. I think will be better to move all warnings on the compilation step, not at the program execution (like in gcc).
@t0md3an #place/print_warning
are done at compile time and don't stop program compilation, they also don't stop program execution because they don't exist at runtime.
The warning(s) printed at runtime shouldn't be seen at every binary execution, because warnings like the ones from 2.4/parse.adept
only show up if the programmer made a mistake.
I think having compile-time warnings for printf would be a good thing, the one problem though is that the compiler can only warn you if the format string is constant. If it isn't constant, then it is impossible for the compiler to know, like in this example:
import basics
func main {
format String = scan("Enter a string with %S in it: ")
printf(format, "apples")
}
It is impossible to know whether printf will crash. And because of this, it is nice to have runtime warnings.
I might add compile-time checking for printf functions (when its available) or something to help prevent against users actually seeing these warnings during runtime. As of now though, you can disable the runtime warnings from printf with this:
#set vsprintf_type_checks false
Then the program will crash silently
@IsaacShelton
Yes, it works, thank you.
Have you planned to add these warnings?:
Declared but not used
\<function> should return \<type>
And some warnings from GNU C compiler
Also I think that the #print/place_error
should abort compilation.
@t0md3an 1.
declared but not used
- I'll probably add in the future<function> should return <type>
- Already exists as an error-Wswitch
which could be added as an exhaustive switch like:
exhaustive switch message.type {
case MessageType::UPDATE
value = message.getContents()
case MessageType::GET
return value
case MessageType::SET
value.store()
}
ERROR: Not all cases covered in exhaustive switch statement.
Missing cases:
case MessageType::CLEAR
case MessageType::DELETE
Overall I think it's better to have the compiler throw an error when it knows something is wrong than to warn you when something might be wrong. Like when the programmer may or may not have intended the switch
to be exhaustive, but with something like this, the compiler knows that you intended on covering all the cases.
#print/place_error
abort compilation, because sometimes you want to have more information about the error after the initial error message.
#print_error "This file requires XYZ"
#print "(You can obtain XYZ from https://xyz.xyz/xyz.zip)"
#halt
However, maybe something like #error
could exist and be equivalent to #print_error #halt
so you get the best of both worlds
#error "This file requires XYZ"
@IsaacShelton Is there any __asm__()
in Adept like in C for calling assembler?
@t0md3an No and I don't really plan on adding one, because it's unnecessary for most programming. I don't think the benefit of adding one is worth the cost of maintaining it.
When it is necessary, Adept supports linking against C libraries, so all assembly can be written inside C and then linked against or can be exposed with C name mangling inside a plain .o
file
@IsaacShelton Is there any way to compile Adept source code for Windows and Linux from MacOS (cross-compilation)?
@t0md3an Not really no, at least not easily. I'll look into it to see how hard it would be.
UPDATE: It turned out to be pretty easy for Windows. I got cross-compiling to work for targeting Windows on MacOS. I've tested it using different parts of the standard library, including OpenGL/GLFW components, and it seems to work really well. I'm pretty sure that if it can handle what I threw at it, then it can cross-compile just about anything.
The once downside though is that cross-compilation support only comes as an extension.
https://github.com/IsaacShelton/AdeptCrossCompilation/releases/
It's really easy to use though and I'm glad you asked about cross-compilation, because it seems to work great. All you gotta do is adept --windows
and you have a working Windows program.
@IsaacShelton
Yes, It works well, this is a good feature for developing cross-platform apps!
1. Also I have a question about building Adept (Makefile) from MacOS for Windows and Linux. Is it possible, or I should use Windows to build Adept for Windows?
2. What utilities requires Adept compiler on Windows, Linux, MacOS?
@t0md3an
It's possible to compile the Adept compiler for Windows while on MacOS. You need to install mingw-w64 with brew install mingw-w64
. Then build llvm either 7 or 10 it shouldn't matter, you have to use CC as x86_64-w64-mingw32-gcc and CXX as x86_64-w64-mingw32-g++ also make sure the llvm build is using mingw32-w64 utils to build it. And then once you have llvm, you can build the compiler, and if the linker fails you'll have to replace LLVM_LIBS under the if(Windows_NT)
branch.
It requires llvm 7 or llvm 10, and optionally libcurl.
@IsaacShelton About n2, I mean what compiler requires after build (ld
, gcc
, opt
etc.)
@t0md3an It requires ld
and a few object files from the mingw64 project and an archive called lipdep.a which I made that contains other necessary object files. The only place to get them easily right now is by either getting ld from mingw64 and .o and libdep.a from the cross compilation extension or you can get the necessary files by installing Adept 2.3 from the Windows installer and going to C:\Adept\2.3\ and copying the .o files, libdep.a, and ld.exe and putting them with your 2.4 build of Adept. Maybe I'll add an entry in the 2.3 releases that contain the necessary files
UPDATE: All of the required files for Adept to run on Windows are now available in a conveniently compressed zip file named Adept-Windows-From-Source-Necessities.zip
under releases.
On Linux, the only runtime requirement is gcc
@IsaacShelton linker warning:
adept main.adept
ld: warning: object file (main.o) was built for newer OSX version (10.15) than being linked (10.13)
How to fix this?
@t0md3an This is fixed now in the latest release
@IsaacShelton
1. For what gcc
is needed in Adept?
2. How this code looks in Adept?
#include <iostream>
int main()
{
int arr[100];
int n; cin >> n;
for (int i = 0; i < n; i++) {
cin >> arr[1];
}
cout << arr[1] << endl;
}
@t0md3an
gcc
is needed on MacOS and Linux in order for Adept to link the generated object file with additional system objects files and archives to create an executable.
Something like
import basics
func main { arr 100 int n int
scan(&n)
repeat n {
scan(&arr[idx])
}
print(arr[1])
}
@IsaacShelton Your code returns this error:
terminal.adept:114:12: Undeclared function 'scanInto'!
114| return scanInto("", result)
^^^^^^^^
@t0md3an This has been fixed now in AdeptImport
@IsaacShelton
1. For what uses funcptr
keyword and function-pointer
type?
2. Why you removed stdio's tmpnam
from cstdio
?
@t0md3an
funcptr
is a left over keyword from Adept 1.1 that isn't used anymore. It has been replaced with func &
in Adept 2.x. The function-pointer
type is a special kind of pointer which can point to functions. Using function pointers, you can call functions based on which function the pointer is pointing to. Function pointers are declared like this:
my_calculate_function func(int, int) int
They can be set to point at functions using func &
my_calculate_function = func &sum(int, int)
And then called like a normal function
result int = my_calculate_function(10, 11)
In this example, the function sum
would be called with the values of 10
and 11
because the function pointer my_calculate_function
points to the function sum
.
I removed tmpnam
because it causes link-time warnings on linux. If you still want to call it, you can force defining it with:
#define sys_cstdio_define_tmpnam true
@IsaacShelton Have you planned to add for (;;) { ... }
loop to Adept and strdup()
to cstring
?
repeat n
loop instead which is equivalent to for(size_t idx = 0; idx < n; idx++) { ... }
.import basics
func main {
scan("Enter a value for n:", def n int)
repeat n {
printf("n = %d\n", idx)
}
}
@IsaacShelton Is it possible to add support for this?
if (1)
{
}
for (;;)
{
}
... other keywords that uses `{}`
If I am trying to use this syntax:
Expected '{' or ',' after conditional expression
NOTE: C allows this syntax
@t0md3an Yes this is now allowed
@IsaacShelton Have you planned to add something like try catch
?
@t0md3an No, I don't plan on adding something like try catch
.
Some other things that I've thought about adding to address the same problems are:
As of now, you still have to do something like this, which is kind of ugly:
func getName(out name *String) successful {
if random(10) < 5, return false
*name = "John"
return true
}
@IsaacShelton
1. What is idx
? Is this is default index value?
2. Have you planned to add python like for
syntax to Adept? I mean two syntaxes:
for (i int; i < n; i++)
for (i in n)
@t0md3an
idx
is like the variable i
, except the language iteself also modifies/accesses the value. It is a variable declared by the compiler when using certain loop types, like repeat
and each-in
, and represents the current index. It is also mutable.import basics
func main {
my_list <int> List
my_list.add(31)
my_list.add(643)
my_list.add(23)
each my_integer int in my_list {
printf("my_list[%d] = %d\n", idx, my_integer)
}
}
my_list[0] = 31
my_list[1] = 643
my_list[2] = 23
idx
is similar to another automatically declared variable called it
, which is the default variable name for the element variable when using each-in
loops.
import basics
func main {
my_list <int> List
my_list.add(31)
my_list.add(643)
my_list.add(23)
// No variable name specified
// \/
each int in my_list {
// Since we didn't specify a variable name for the current element, the default name of 'it' is used
printf("my_list[%d] = %d\n", idx, it)
}
}
my_list[0] = 31
my_list[1] = 643
my_list[2] = 23
for i int = 0; i < 10; i++ { /* ... */ }
for(i int = 0; i < 10; i++){ /* ... */ }
for i int = 0; i < 10; i++, /* ... */
for(i int = 0; i < 10; i++), /* ... */
and for python-style for-in loops, we already have the each-in
loop:
import basics
func main {
my_list <int> List
my_list.add(1)
my_list.add(2)
my_list.add(3)
each my_value int in my_list {
print(my_value)
}
}
and for python for-in-range loops, we have something similar called repeat
, except the starting index is always 0.
import basics
func main {
repeat 4 {
printf("%d\n", idx)
}
}
0
1
2
3
@IsaacShelton Also have you planned to add union
/extern
/typedef
keywords and extern "C"
functionality?
@t0md3an Yes. We already have extern / extern "C"
in the form of the external
and foreign
keywords. external
is used for global variables, and foreign
is used for functions. They both use C name-mangling conventions and non-private linking. For example, errno
is declared as:
external thread_local errno int
And printf(*ubyte, ...)
is declared as:
foreign printf(*ubyte, ...) int
We also already have typedef
in the form of alias
. For example:
alias GLsizei = int
alias GLboolean = bool
alias GLbyte = byte
alias GLubyte = ubyte
alias GLshort = short
alias GLushort = ushort
alias GLint = int
alias GLuint = uint
alias GLfloat = float
alias GLclampf = float
alias GLdouble = double
alias GLclampd = double
alias GLenum = uint
alias GLbitfield = uint
// ...
What we don't have yet is union
, which I've thought about adding but haven't really had a need for yet. Maybe I'll add it sometime soon, It shouldn't be that hard to do.
@IsaacShelton How to create a custom data type in Adept? (I mean something like time_t
) In C for this can be used typedef
or struct
.
@t0md3an You can create custom data types by either using alias
or struct
. To start off, aliases are of course just alternative names for a different type. For example:
alias time_t = long
alias CString = *ubyte
Types declared with alias
are treated the same as the type they are declared as (so long
and time_t
would be interchangeable in the previous example). For creating structure types, you can create them using struct
and specifying a list of fields.
struct Person (name String, age int)
struct Book (
title String,
author String,
subject String,
id int
)
which is the same as the C code:
typedef struct {
/* ... */
} Person;
Also in Adept, if multiple fields in a row have the same type, you only have to specify the type once, for example:
struct Book (
title String,
author String,
subject String,
id int
)
// is the same as
struct Book (title, author, subject String, id int)
You can use these user-defined types like you would any other types:
import basics
struct Person (firstname, lastname String)
func main {
person Person
scan("Enter your firstname: ", &person.firstname)
scan("Enter your lastname: ", &person.lastname)
printf("Hello there %S %S!\n", person.firstname, person.lastname)
}
@IsaacShelton
1. I think it will be good if Adept'll allow this:
someFunc int = func (num int) {
return num + num
}
func main()
{
print(someFunc(1)) // 2
}
2. Please, write a table like this for all Adept data types (this is for more understanding Adept data types):
name | designation |
---|---|
int |
%i |
@t0md3an
Vector3f :: struct (x, y, z float)
someFunc :: func (num int) int { return num + num }
main :: func { print(someFunc(1)) }
But right now I'm not completely sold on the idea.. Sometimes I like the `::` syntax a little better, but other times I don't. As of now, I'm not going to plan on adding alternative syntax for that, because I would want to retain the ability to use the current syntax for backwards-compatibility, and then it would fracture the language into two subsets that would make learning Adept harder. And if/when you mix the two syntaxes, you get the worst of both worlds:
struct Vector3f (x, y, z float) Person :: struct (firstname, lastname String)
someFunc :: func (num int) int { return num + num }
func main { print(someFunc(1)) }
2. I'm still working on specifiers for some types, but as of now this is the table:
| name | designation |
|----|----|
| `bool` | `%B` for `true`/`false`, `%y` for `yes`/`no`, `%Y` for `Yes`/`No`|
| `byte` | doesn't have one yet, so use `%d` |
| `ubyte` | doesn't have one yet, so use `%d` or `%u` |
| `short` | doesn't have one yet, so use `%d` |
| `ushort` | doesn't have one yet, so use `%d` or `%u` |
| `int` | `%d` |
| `uint` | `%u` |
| `long` | `%l` |
| `ulong` | doesn't have one yet, so use `%u` |
| `usize` | doesn't have one yet, so use `%u` |
| `float` | doesn't have one yet, so use `%f` |
| `double` | `%f` |
| `*ubyte` | `%s` |
| `String` | `%S` |
| `ptr`/`*WhateverType` | `%p` |
I'm planning on completing these specifiers to be something like:
| name | designation |
|----|----|
| `bool` | `%b` or `%B` for `true`/`false`, `%y` for `yes`/`no`, `%Y` for `Yes`/`No`|
| `byte` | `%hhd` or `%hhi`|
| `ubyte` | `%hhu` for numeric value, `%c` for character value |
| `short` | `%hd` or `%hi` |
| `ushort` | `%hu` |
| `int` | `%d` or `%i` |
| `uint` | `%u` |
| `long` | `%ld` or `%li` or `%lld` or `%lli` |
| `ulong` | `%lu` or `%llu` |
| `usize` | `%zu` |
| `float` | `%hf` |
| `double` | `%f` |
| `*ubyte` | `%s` |
| `String` | `%S` |
| `ptr`/`*WhateverType` | `%p` |
@IsaacShelton Yes, I think ::
is better, I think you should add it (just for pro programmers). I like this ::
, it's beautiful.
You can also add :
for variables to do something like this:
main :: func() : int {
num : int = 0
return 0
}
This variable definition is more logical than just num int
(I have been confused about this more than once, I mean that I was confused about where is the variable and where is the type, but the num : int
shows that num is :
int). I think it's more understandable.
And for enum
, union
and struct
:
Person :: struct ()
Fruit :: enum ()
Some :: union ()
I think this is more logical and more understandable.
@t0md3an I'm not gonna make it a standard part of the language until I'm certain it's a good thing, but I've added an experimental version to see how it fares since you think it could be a good thing. You can pull it down and test it out
pragma enable_experimental_colon_colon_syntax
pragma enable_experimental_colon_before_type_syntax
import basics
Person :: struct (firstname, lastname String)
main :: func {
person: Person
scan("Enter your name: ", &person.firstname)
myPrintf("Hello %S!", person.firstname)
}
myPrintf :: func (format String, arguments ...) : int {
name: String = "Hello"
vsprintf(def result String, format, arguments)
print(result)
return 0
}
You need to have the following pragma directives to enable it:
pragma enable_experimental_colon_colon_syntax
pragma enable_experimental_colon_before_type_syntax
I reserve the right to remove this at any point in the future, so just be prepared for if I decide to remove it
One idea would be to allow the programmer to customize the language's syntax to a limited degree, I think that could be a good compromise. Everyone gets to use the syntax they like best, and the language isn't so rigid syntax-wise. I don't know if I'll actually do that, but it's something I'm considering. All standard library code would be written in the whatever the default syntax is, and if the user wants to use different syntax for their funcs/structs/enums/unions/whatever that's their decision. Again this is just an idea, I may or may not choose to do this
Update:
After playing with the :
before types syntax, I personally don't like it. Not planning to make it the standard.
Regarding the ::
syntax, I kinda like it, still has the issues I mentioned a few messages ago though. For now I plan to keep it as an experimental syntax until I decide whether or not I want to officially support it
@IsaacShelton I have an idea for defining variables, you can do something like this:
// one of these:
num = 0 : int // I think it's better
num = 0 -> int
num = 0 int
because the beginner can get confused by the default entry:
num int = 0
beginner can think that int = 0
, not num = 0
.
But this is just an idea.
@t0md3an I've thought about different ways of doing syntax around types, and every one of them has advantages and disadvantages.
With the num : int = 0
syntax:
[+]
Clearly distinguishes between type and variable name[+]
Similar enough to mainstream languages[-]
Isn't easy on the eyes[-]
Slows down typingWith the num = 0 : int
, num = 0 -> int
syntax:
[+]
Clearly distinguishes between type and variable name[-]
Isn't easy on the eyes[-]
Unnatural thought ordering[-]
Slows down typing[-]
Doesn't have any similarities to mainstream languages[-]
Difficult for compiler to understandWith the num = 0 int
syntax:
[-]
Fails to clearly distinguish between type and expression value[-]
Unnatural thought ordering[-]
Doesn't have any similarities to mainstream languages[-]
Difficult for compiler to understand[+]
Quick to type, no symbols except =
With the num int = 0
syntax:
[-]
Variable name and type can become confusing when not using syntax highlighting[+]
Similar enough to mainstream languages[+]
Beautiful and easy on the eyes[+]
Quick to type, no symbols except =
From my analysis on the different ways of doing it, I still believe that num int = 0
is the best way. And num : int = 0
comes in at second place. The tradeoff between the two is speed of typing and looks versus clarity for beginners. I think that since Adept isn't intended for beginners, and is intended primarily for only a few people, the benefits of num int
are worth the tradeoff. Plus, when you're using syntax highlighting or user-defined types, the issue of confusion goes away for the most part. And for the few times that confusion could take for beginners, it's set up in such a way that most people could understand that type type/variable name are reversed. And for the programmers who know what they're doing with Adept, it quickly becomes something that they're used to.
On another note, I've been considering ::
syntax to become official maybe in Adept 2.5
if I still like it by the time. I like the way it looks and it feels more robust. It also matches the way Adept does variables, with the name coming before the definition, which I think brings more consistency to the language and it makes it easy to glance through functions/methods. Of course the old syntax of func functionName() void
would still be supported for backwards-compatibility with versions 2.0
-2.4
.
With the amount of work I've been doing on Adept lately, I could decide to release Adept 2.4
sometime in the next few months. Then the transition would take place at the beginning of Adept 2.5
for having ::
become the standard syntax.
@IsaacShelton What is ubyte
(*ubyte
, **ubyte
)?
@t0md3an ubyte
in an unsigned 8-bit integer. It takes up one byte of space (sizeof ubyte == 1
) and can represent values from 0-255. Just like char
in C, it's used as the type to hold an ascii character, but unlike in C, it is guaranteed to be unsigned.
*ubyte
is pointer to a location in memory where one or more ubyte
s are stored.
**ubyte
is pointer to a pointer to a location in memory where one or more ubyte
s are stored.
Here's a graphic explaining it better, if you have some experience with C then its basically the same thing
Just like in C where []/*
are interchangable, pointers to values in memory don't indicate how many of what they point to is there. So **ubyte
could be a pointer to a C-String, or it could be a location in memory where several C-Strings are stored.
Hopefully this explanation helps
@t0md3an
- I'm not completely sure whether adding syntax like that would be good or not. If I ever end up doing something like that, it would probably use syntax like:
Vector3f :: struct (x, y, z float) someFunc :: func (num int) int { return num + num } main :: func { print(someFunc(1)) }
But right now I'm not completely sold on the idea.. Sometimes I like the
::
syntax a little better, but other times I don't. As of now, I'm not going to plan on adding alternative syntax for that, because I would want to retain the ability to use the current syntax for backwards-compatibility, and then it would fracture the language into two subsets that would make learning Adept harder. And if/when you mix the two syntaxes, you get the worst of both worlds:struct Vector3f (x, y, z float) Person :: struct (firstname, lastname String) someFunc :: func (num int) int { return num + num } func main { print(someFunc(1)) }
- I'm still working on specifiers for some types, but as of now this is the table:
name designation
bool
%B
fortrue
/false
,%y
foryes
/no
,%Y
forYes
/No
byte
doesn't have one yet, so use%d
ubyte
doesn't have one yet, so use%d
or%u
short
doesn't have one yet, so use%d
ushort
doesn't have one yet, so use%d
or%u
int
%d
uint
%u
long
%l
ulong
doesn't have one yet, so use%u
usize
doesn't have one yet, so use%u
float
doesn't have one yet, so use%f
double
%f
*ubyte
%s
String
%S
ptr
/*WhateverType
%p
I'm planning on completing these specifiers to be something like:name designation
bool
%b
or%B
fortrue
/false
,%y
foryes
/no
,%Y
forYes
/No
byte
%hhd
or%hhi
ubyte
%hhu
for numeric value,%c
for character valueshort
%hd
or%hi
ushort
%hu
int
%d
or%i
uint
%u
long
%ld
or%li
or%lld
or%lli
ulong
%lu
or%llu
usize
%zu
float
%hf
double
%f
*ubyte
%s
String
%S
ptr
/*WhateverType
%p
@IsaacShelton I saw that you have changed something in data types specifiers (%...
) at the last commits, now which one table of types is valid?
@t0md3an Yeah I finished implementing the rest of the specifiers, this is the full table:
name | designation |
---|---|
bool |
%b or %B for true /false , %y for yes /no , %Y for Yes /No |
byte |
%hhd or %hhi |
ubyte |
%hhu for numeric value, %c for character value |
short |
%hd or %hi |
ushort |
%hu |
int |
%d or %i |
uint |
%u |
long |
%ld or %li or %lld or %lli |
ulong |
%lu or %llu |
usize |
%zu |
float |
%hf |
double |
%f |
*ubyte |
%s |
String |
%S |
ptr /*WhateverType |
%p |
This of course only applies to the printf(String, arguments ...)
version of printf and not printf(*ubyte, ...)
.
If runtime type information isn't disabled, then %d
, %i
, %u
, and %f
specifiers aren't picky about whether you give them the exact type they expect.
@IsaacShelton
1. How to printf **WhateverType
? Like *
%p?
2. How to printf List
? Using it’s type?
3. What is ulong
, ushort
and usize
and what difference between long
, short
and size
?
4. What difference between byte
and ubyte
?
5. Why there is no unsigned float ufloat
/unsigned float
?
6. Can I do something like long long int
in Adept?
Thanks
@t0md3an
Yeah since **WhateverType
is still just a pointer, you use %p
.
To printf List
, you have to convert it to a String
. With the latest build of AdeptImport
you can do:
import basics
func main {
list
func getList
Otherwise, without using any recent stuff, you can just use an `each-in` loop to print each element:
import basics
func main {
list
3. To start off, here is a table of all the primitive types:
| Primitive Type | Bits | Signed-ness | Possible Values | C Equivalent (Roughly) |
|----|----|----|----|----|
| `bool` | 1 bit | ~ | true or false | `bool` |
| `byte` | 8 bits | signed | -128..127 | `signed char` |
| `short` | 16 bits | signed | -32,768..32,767 | `short` |
| `int` | 32 bits | signed | -2,147,483,648..2,147,483,647 | `int` |
| `long` | 64 bits | signed | -9e18..9,223,372,036,854,775,807 | `long long` |
| `ubyte` | 8 bits | unsigned | 0..255 | `unsigned char` |
| `ushort` | 16 bits | unsigned | 0..65,535 | `unsigned short` |
| `uint` | 32 bits | unsigned | 0..4,294,967,295 | `unsigned int ` |
| `ulong` | 64 bits | unsigned | 0..18,446,744,073,709,551,615 | `unsigned long long` |
| `usize` | 64 bits | unsigned | 0..18,446,744,073,709,551,615 | `size_t` |
| `float` | 32 bits | ~ | 3.4E +/- 38 (7 digits) | `float` |
| `double` | 64 bits | ~ | 1.7E +/- 308 (15 digits) | `double` |
| `ptr`/`*` | 64 bits | unsigned | Any Memory Address | `void*` / `*` / `[]` |
There are 4 main types. They are `byte`, `short`, `int`, and `long`. They are 8 bits, 16 bits, 32 bits, and 64 bits in size respectively. They can also be prefixed with `u` to make them unsigned. When they are unsigned, they lose the ability to hold negative numbers, but they gain the ability to hold more positive numbers. In addition to these types, we have `bool` which of course is a boolean that can hold true or false. We also have `float` and `double` which are the two floating point number options, which are 32 bits and 64 bits in size respectively. Then we also have `usize` which does NOT have a signed variant. It is used to hold lengths or sizes of things. The reason why there is no `size` type is because length and size measurements can never be negative, so we always use `usize`. And lastly we have the pointer types. Which includes `*` types and the special `ptr` type. The `ptr` type is a pointer to an unspecified type, just like `void*` is in C.
With that knowledge, we can now differentiate these types:
**`ulong`** is an unsigned 64-bit integer, which means it can hold positive integers up to 2^64-1. so values 0..18,446,744,073,709,551,615.
**`ushort`** is an unsigned 16-bit integer, which means it can hold positive integers up to 2^16-1, so values 0..65,535.
**`usize`** is an unsigned integer used to hold sizes or lengths, currently it's an unsigned 64-bit integer, so it's identical to `ulong`
**`short`** is signed 16-bit integer, which means it can hold positive and negative integers -32,768..32,767.
**`long`** is signed 64-bit integer, which means it can hold positive and negative integers -9,223,372,036,854,775,808..9,223,372,036,854,775,807.
**`size`** does not exist, since lengths and size measurements are always positive, we always use `usize`.
4. The difference is that `byte` is signed, where as `ubyte` is unsigned.
`byte` can hold values -128..127.
`ubyte` can hold values 0..255.
5. Because CPUs don't support unsigned floats. In 99% of cases, you want floats to be able to hold negative numbers.
6. `long long int` is a signed 64-bit integer in C (usually). In Adept we have `long`, which is the same thing.
@IsaacShelton Have you planned to allow this (()
in syntax):
sizeof(...) // now only sizeof value, if I uses `()` it does not works
new(...)
delete(...)
other keywords with this syntax...
@IsaacShelton
When you'll release documentation for Adept? (I really want to learn Adept.)
Is there any way to read command-line arguments like in C?