Page 9 of 11
Re: Why are ASM hobby OS more successful than other language
Posted: Thu Dec 15, 2011 6:30 pm
by Rusky
Brendan wrote:Ah - now I understand. The underscore character on line 70 ("_ -> /* no rsdt */") is your renamed NULL.
Actually, no. I don't understand the line above it ("real_rsdt: acpi_rsdt* -> parse_acpi_tables(real_rsdt)") which looks like it creates a variable called "read_rsdt" of type "acpi_rsdt*" and assigns the value returned by "parse_acpi_tables(real_rsdt)" to the variable. In C syntax it'd be "acpit_rsdt *read_rsdt = parse_acpi_tables(real_rsdt);", and you'd get a warning about using an uninitialised variable as the argument to "parse_acpi_tables()".
It's pattern matching- the underscore is like a default label in a switch statement. It means "anything not matched above," while the line above it means "put optional_rsdt in the new variable real_rsdt if it 'fits' in that type." It's how I extracted the value from optional_rsdt- the match statement is a null check. Because you're allergic to functional programming, which I obviously shouldn't have mentioned, here's the C syntax:
Code: Select all
if (optional_rsdt) {
acpi_rsdt *real_rsdt = optional_rsdt;
parse_acpi_tables(real_rsdt);
}
else {
/* no rsdt */
}
Brendan wrote:How does the "controller <= madt->controllers[-1]&;" make sense? Should I translate it into "stop looping if the starting address of the current controller is not lower than or equal to the starting address of the last entry in a heterogeneous array that isn't a heterogeneous array"?
Wouldn't it make more sense to do "stop looping if the address of the "length" field in the controller structure would be past the end of the parent "acpi_madt" structure; and (if the first check passes and you can safely use the length field of the controller structure) also stop looping if the "controller start address plus controller length field" is beyond the size of the parent acpi_madt structure"?
madt->controllers is a byte array with its contents being cast to different-sized structures, not "a heterogeneous array that isn't a heterogeneous array." But yes, it would make more sense to check if the length field of the current controller goes past the madt structure. That would be caught by the compiler in this imaginary language. Would it be caught in C?
Brendan wrote:Given a correct RSDT? Nobody said it's a correct RSDT.
If you can't rely on the length fields of the ACPI structures, you're screwed anyway and you'd get the same checksum result no matter how you write the program. At that point, the problem is in the firmware. Besides, as we all know this is a systems programming language and the goal is not 100% memory safety, just an improvement over the brain-dead type checker that is C's.
Brendan wrote:I don't think that the ability to do compile time enforcement of explicit run-time checking is realistic either (another "sounds easy to do until you attempt to implement a compiler that does it" feature).
I've already explained how this is possible, but that discussion got sidetracked onto functional programming because you're allergic to academia and refuse to look at research papers that explain the details.
Re: Why are ASM hobby OS more successful than other language
Posted: Thu Dec 15, 2011 9:13 pm
by Brendan
Hi,
Rusky wrote:Brendan wrote:Actually, no. I don't understand the line above it ("real_rsdt: acpi_rsdt* -> parse_acpi_tables(real_rsdt)") which looks like it creates a variable called "read_rsdt" of type "acpi_rsdt*" and assigns the value returned by "parse_acpi_tables(real_rsdt)" to the variable. In C syntax it'd be "acpit_rsdt *read_rsdt = parse_acpi_tables(real_rsdt);", and you'd get a warning about using an uninitialised variable as the argument to "parse_acpi_tables()".
It's pattern matching- the underscore is like a default label in a switch statement. It means "anything not matched above," while the line above it means "put optional_rsdt in the new variable real_rsdt if it 'fits' in that type." It's how I extracted the value from optional_rsdt- the match statement is a null check. Because you're allergic to functional programming, which I obviously shouldn't have mentioned, here's the C syntax:
Code: Select all
if (optional_rsdt) {
acpi_rsdt *real_rsdt = optional_rsdt;
parse_acpi_tables(real_rsdt);
}
else {
/* no rsdt */
}
Ah - it's just confusing when the syntax looks like you're creating a new variable and not doing "case" or pattern matching at all. What makes it more confusing is that "->" is used to refer to a field in a structure (e.g. "table->length"). Giving symbols multiple meanings (where meaning depends on context) is something I don't like in any language (including '&' and "*' in C).
Anyway, basically what you're saying is that "acpi_rsdt*" pointer type doesn't accept NULL and the "acpi_rsdt?" pointer type does, so the matching works by checking to see if the pointer is NULL in an obfuscated way.
What if the 32-bit pointer is 0xFFFFFFFF - would the compiler think it's a valid pointer? What if the kernel is 64-bit?
Rusky wrote:madt->controllers is a byte array with its contents being cast to different-sized structures, not "a heterogeneous array that isn't a heterogeneous array." But yes, it would make more sense to check if the length field of the current controller goes past the madt structure. That would be caught by the compiler in this imaginary language. Would it be caught in C?
It would be caught in imaginary C, but not real C...
Rusky wrote:Brendan wrote:Given a correct RSDT? Nobody said it's a correct RSDT.
If you can't rely on the length fields of the ACPI structures, you're screwed anyway and you'd get the same checksum result no matter how you write the program. At that point, the problem is in the firmware. Besides, as we all know this is a systems programming language and the goal is not 100% memory safety, just an improvement over the brain-dead type checker that is C's.
You can at least check if the length field is large enough for a valid (required) header, and is below an arbitrary maximum (e.g. is a 3 GiB RSDT likely to be sane?). A good assembly or C programmer would check these things (after being kicked in the groin enough times, you learn to protect your groin).
Rusky wrote:Brendan wrote:I don't think that the ability to do compile time enforcement of explicit run-time checking is realistic either (another "sounds easy to do until you attempt to implement a compiler that does it" feature).
I've already explained how this is possible, but that discussion got sidetracked onto functional programming because you're allergic to academia and refuse to look at research papers that explain the details.
That discussion was about array bounds checking.
Consider this code (Java):
Code: Select all
public class Person {
private int age; // Stupid java doesn't support unsigned integers...
Person(int newAge) {
age = newAge;
}
}
Now write a compiler that generates a "You need an explicit check" error for the bug in the code above.
Cheers,
Brendan
Re: Why are ASM hobby OS more successful than other language
Posted: Thu Dec 15, 2011 10:22 pm
by Rusky
Brendan wrote:Ah - it's just confusing when the syntax looks like you're creating a new variable and not doing "case" or pattern matching at all. What makes it more confusing is that "->" is used to refer to a field in a structure (e.g. "table->length"). Giving symbols multiple meanings (where meaning depends on context) is something I don't like in any language (including '&' and "*' in C).
Agreed. Thus my disclaimers about syntax- in that instance I just stole an existing syntax for pattern matching. Use a different symbol if you like, it doesn't hurt the language's real purpose.
Brendan wrote:Anyway, basically what you're saying is that "acpi_rsdt*" pointer type doesn't accept NULL and the "acpi_rsdt?" pointer type does, so the matching works by checking to see if the pointer is NULL in an obfuscated way.
What if the 32-bit pointer is 0xFFFFFFFF - would the compiler think it's a valid pointer? What if the kernel is 64-bit?
You're entitled to your opinion of whether it's obfuscated or not, but the reason I did it that way is to emphasize that you cannot dereference an acpi_rsdt? without extracting an acpi_rsdt* from it, which requires an explicit branch between the case where there is an acpi_rsdt* and where there isn't. If there is an acpi_rsdt*, whether it's valid or not is proven (or hoped for) where such details belong: at the creation of the acpi_rsdt?.
Brendan wrote:It would be caught in imaginary C, but not real C...
It
is caught, today, in the panoply of languages I cited for you in the dependent typing discussion.
Brendan wrote:You can at least check if the length field is large enough for a valid (required) header, and is below an arbitrary maximum (e.g. is a 3 GiB RSDT likely to be sane?). A good assembly or C programmer would check these things (after being kicked in the groin enough times, you learn to protect your groin).
If you need to operate on that broken of firmware, bootloader, paging setup, etc., you can add that kind of check yourself or improve on my top-of-my-head design. That is
no worse than C, while this kind of language does
more in other areas, so I don't see how that damages my claim that such a language would be an improvement.
Brendan wrote:Consider this code (Java):
...
Now write a compiler that generates a "You need an explicit check" error for the bug in the code above.
What explicit check? You didn't tell the compiler you wanted age to be non-negative. In the language I'm proposing, you would. C and C++, with all warnings enabled, don't even complain about "
unsigned int a = -5;".
Re: Why are ASM hobby OS more successful than other language
Posted: Thu Dec 15, 2011 11:25 pm
by Solar
Rusky wrote:In the language I'm proposing, you would. C and C++, with all warnings enabled, don't even complain about "unsigned int a = -5;".
I beg to differ. -Wconversion has been around a while.
Re: Why are ASM hobby OS more successful than other language
Posted: Fri Dec 16, 2011 12:09 am
by Brendan
Hi,
Rusky wrote:Brendan wrote:Consider this code (Java):
...
Now write a compiler that generates a "You need an explicit check" error for the bug in the code above.
What explicit check? You didn't tell the compiler you wanted age to be non-negative. In the language I'm proposing, you would. C and C++, with all warnings enabled, don't even complain about "
unsigned int a = -5;".
If I can tell the compiler I want age to be non-negative, why can't I tell the compiler I want age to be within the range 0 to 200 (and then not bother telling the compiler if it's signed or unsigned; or char, short, int or long)? If I can tell the compiler I want a variable to be within a certain range, why can't I do the same with pointers (e.g. "
acpi_rsdt* must be in the range from 1 to (0x100000000 - sizeof(acpi_header))")?
Cheers,
Brendan
Re: Why are ASM hobby OS more successful than other language
Posted: Fri Dec 16, 2011 2:58 am
by turdus
@Brendan, Rusky: I think what you're talking about is supported by ADA95 language. It also has a runtime checker though (compile time checking is simply not enough), for situations like
Code: Select all
unsigned int age=5;
unsigned int delta=0;
delta=somefunction(); //returns 10 when executed under some circumstances
age-=delta;
Here's the manual on how to do this in Ada95, with some examples:
http://www.adahome.com/rm95/rm9x-03-02-02.html
Ada allows to be more precise if you want:
Code: Select all
subtype age is Integer range 0..110;
subtype grownupage in age range 18..110;
This will throw a Constraint_Error exception if you try to load a value out of range into a variable of type age on execution, and won't compile if it happens in a declaration.
Re: Why are ASM hobby OS more successful than other language
Posted: Fri Dec 16, 2011 10:23 am
by Rusky
Solar wrote:I beg to differ. -Wconversion has been around a while.
It's not included in "
-Wall -Wextra -pedantic", my bad (sort of).
turdus wrote:@Brendan, Rusky: I think what you're talking about is supported by ADA95 language. It also has a runtime checker though (compile time checking is simply not enough), for situations like
Code: Select all
unsigned int age=5;
unsigned int delta=0;
delta=somefunction(); //returns 10 when executed under some circumstances
age-=delta;
Here's the manual on how to do this in Ada95, with some examples:
http://www.adahome.com/rm95/rm9x-03-02-02.html
Ada allows to be more precise if you want:
Code: Select all
subtype age is Integer range 0..110;
subtype grownupage in age range 18..110;
This will throw a Constraint_Error exception if you try to load a value out of range into a variable of type age on execution, and won't compile if it happens in a declaration.
Ah yes. I knew Ada was good with type safety but I was not aware of the specifics. However, compile time checking could help with that example- with the return type of
somefunction specified as "0..10" or whatever, the compiler would notify the programmer of the potential error and then it would be their responsibility to handle the error in the way they choose, rather than through exceptions they may or may not remember to handle.
Brendan wrote:If I can tell the compiler I want age to be non-negative, why can't I tell the compiler I want age to be within the range 0 to 200 (and then not bother telling the compiler if it's signed or unsigned; or char, short, int or long)? If I can tell the compiler I want a variable to be within a certain range, why can't I do the same with pointers (e.g. "acpi_rsdt* must be in the range from 1 to (0x100000000 - sizeof(acpi_header))")?
You can- that would be an "improve[ment] on my top-of-my-head design" using dependent types
Re: Why are ASM hobby OS more successful than other language
Posted: Fri Dec 16, 2011 12:36 pm
by Brendan
Hi,
berkus wrote:Brendan wrote:If I can tell the compiler I want age to be non-negative, why can't I tell the compiler I want age to be within the range 0 to 200 (and then not bother telling the compiler if it's signed or unsigned; or char, short, int or long)? If I can tell the compiler I want a variable to be within a certain range, why can't I do the same with pointers (e.g. "acpi_rsdt* must be in the range from 1 to (0x100000000 - sizeof(acpi_header))")?
So you DO want dependant types now?
I don't see it as dependant types - the type of a variable doesn't depend on the variable's value (only the variable's range).
We already specify a variable's range when we say its type (e.g. char, unsigned short, etc). The idea is to allow the range to be specified much more accurately, so that we can remove most primitive types (e.g. only have 3 primitive types - pointers, integers and floating point).
It would also help to remove the effect of some of the stupid misinformation people have learnt; like "an 8-bit integer can only hold values from 0 to 255 (if unsigned) or from -128 to 127 (if signed)". For example, what if we have an "age" variable and say that the allowed range is from -1 to 200 (where -1 is used for "unknown"). A compiler could be smart enough to see this and decide that it fits in an 8-bit integer, even though it wont fit in an "unsigned char" or a "signed char".
As an added bonus, it'd help with portability - I'd bet there's thousands of C programmers that think it's safe to store the value 0xFFFF in an "int" because it's always worked on their machines.
Solar wrote:I beg to differ. -Wconversion has been around a while.
That works (for a relatively limited definition of "works").
The problem is that GCC won't track the maximum/minimum range of values throughout a program. This means you can do:
Code: Select all
int foo = 123;
unsigned int bar = foo;
And you get an unnecessary
"warning: conversion to ‘unsigned int’ from ‘int’ may change the sign of the result". It's these unnecessary warnings that make "-Wconversion" unusable.
Cheers,
Brendan
Re: Why are ASM hobby OS more successful than other language
Posted: Fri Dec 16, 2011 1:14 pm
by Rusky
Brendan wrote:I don't see it as dependant types - the type of a variable doesn't depend on the variable's value (only the variable's range).
That's what dependent types
are. The type doesn't have to depend on the variable's value, just on
a value. Arrays with their length in the type are dependent types. Integers with a specific range are dependent types (although generally only when it's more specific than whatever happens to be built-in to the processor). It's nice to know we agree on something.
Re: Why are ASM hobby OS more successful than other language
Posted: Fri Dec 16, 2011 3:03 pm
by Brendan
Hi,
Rusky wrote:Brendan wrote:I don't see it as dependant types - the type of a variable doesn't depend on the variable's value (only the variable's range).
That's what dependent types
are. The type doesn't have to depend on the variable's value, just on
a value. Arrays with their length in the type are dependent types. Integers with a specific range are dependent types (although generally only when it's more specific than whatever happens to be built-in to the processor). It's nice to know we agree on something.
Doh. From the
wikipedia article I assumed that "
a dependent type is a type that depends on a value" (and therefore wasn't a type that depended on a range of many possible values, because "a value" isn't "a range of values").
Let's draw up a summary then...
Things we seem to agree on:- Variables (including pointers) should have ranges
- Using the same symbols for different things is bad (e.g. '*' and '&' in C)
- Functions should be able to return multiple values
Things we may or may not agree on:- Unless there's a good reason, the syntax should be similar to whatever people are already familiar with (mostly "C like" syntax).
- For any new technology (including languages and operating systems), the benefits of that new technology need to outweigh the cost of changing from old technology (retooling, retraining, etc).
- Functional programming is imperative programming with an additional set of restrictions (and work-arounds for the restrictions), where these additional restrictions (and work-arounds) are intended to avoid common problems with imperative programming; but the restrictions are often worse than the problems they intend to avoid because:
- It causes too much change in syntax
- It causes too much change in the way programmers have to think
- The benefits are negligible because programmers are already comfortable dealing with most of the problems that functional programming attempts to solve (everything except concurrency)
- There's better ways to handle concurrency
- The biggest problem with modern languages is that they're text based. You should be able drag and drop icons directly into something like a class diagram to create a program's logic. Note: I mean honestly, computers only ever do about 15 simple operations (call, return, jmp/goto, branch/if, loops, add, subract, multiply/shift left, divide/shift right, not, and, or, xor, copy) - why the hell is programming so freaking complicated to begin with!
Cheers,
Brendan
Re: Why are ASM hobby OS more successful than other language
Posted: Fri Dec 16, 2011 4:54 pm
by Rusky
Brendan wrote:Doh. From the
wikipedia article I assumed that "
a dependent type is a type that depends on a value" (and therefore wasn't a type that depended on a range of many possible values, because "a value" isn't "a range of values").
Why isn't an ordered pair a value?
Brendan wrote:Let's draw up a summary then...
Add these to "Things we seem to agree on:"
Brendan wrote:- Unless there's a good reason, the syntax should be similar to whatever people are already familiar with (mostly "C like" syntax).
- For any new technology (including languages and operating systems), the benefits of that new technology need to outweigh the cost of changing from old technology (retooling, retraining, etc).
- Text-based programming has problems caused by its free-form nature that don't exist in well-designed GUI-based programming.
Brendan wrote:- Functional programming is imperative programming with an additional set of restrictions (and work-arounds for the restrictions), where these additional restrictions (and work-arounds) are intended to avoid common problems with imperative programming; but the restrictions are often worse than the problems they intend to avoid because:
- It causes too much change in syntax
- It causes too much change in the way programmers have to think
- The benefits are negligible because programmers are already comfortable dealing with most of the problems that functional programming attempts to solve (everything except concurrency)
- There's better ways to handle concurrency
I'm not going to start the functional programming debate again, but you're right that I strongly disagree with these points.
Re: Why are ASM hobby OS more successful than other language
Posted: Fri Dec 16, 2011 4:54 pm
by NickJohnson
Brendan wrote:Functional programming is imperative programming with an additional set of restrictions (and work-arounds for the restrictions), where these additional restrictions (and work-arounds) are intended to avoid common problems with imperative programming; but the restrictions are often worse than the problems they intend to avoid because:
I think this is your problem. To me, functional programming means the opposite: a set of extensions to the language that
allow you to write programs in a way that nicely avoids some of the problems with imperative languages. A super-powered static type system that eliminates side effects like the one in Haskell is nice for some things, but I don't think it's the essence of functional programming. All you need for real functional programming is a) closures, b) garbage collection, and c) proper lexical scoping.
C has none of these, but you still can see examples of functional programming in C. Take the qsort() standard library function, for example: it uses a function pointer as a surrogate closure to make itself highly generic. Whenever you use a function pointer for something other than registering a callback, you're using a functional style. Things like map, reduce, and filter all do this sort of thing, and are the bread and butter of functional design. Avoiding mutable state is just natural when using a functional style (particularly with garbage collection) IMO, making it more of a ... (puts on shades) ... side effect.
Brendan wrote:The biggest problem with modern languages is that they're text based. You should be able drag and drop icons directly into something like a class diagram to create a program's logic.
Note: I mean honestly, computers only ever do about 15 simple operations (call, return, jmp/goto, branch/if, loops, add, subract, multiply/shift left, divide/shift right, not, and, or, xor, copy) - why the hell is programming so freaking complicated to begin with!
Aaahhh! The pain! Why would that ever be faster than just typing? Text is a type of image too, you know, if you bother to format it correctly. It's also very transparent.
Re: Why are ASM hobby OS more successful than other language
Posted: Fri Dec 16, 2011 5:28 pm
by Brendan
Hi,
NickJohnson wrote:All you need for real functional programming is a) closures, b) garbage collection, and c) proper lexical scoping.
Various imperative programming languages have some or all of these things. They have nothing to do with functional programming.
NickJohnson wrote:Brendan wrote:The biggest problem with modern languages is that they're text based. You should be able drag and drop icons directly into something like a class diagram to create a program's logic.
Note: I mean honestly, computers only ever do about 15 simple operations (call, return, jmp/goto, branch/if, loops, add, subract, multiply/shift left, divide/shift right, not, and, or, xor, copy) - why the hell is programming so freaking complicated to begin with!
Aaahhh! The pain! Why would that ever be faster than just typing? Text is a type of image too, you know, if you bother to format it correctly. It's also very transparent.
What's easier to understand and maintain - a flowchart, or text in some formal language?
Let's have a slide show. For each of these pictures, I want you to try to imagine writing a description in a formal "text only" language:
Now try to explain why programming is the only "engineering like" profession that uses text.
Cheers,
Brendan
Re: Why are ASM hobby OS more successful than other language
Posted: Fri Dec 16, 2011 5:43 pm
by gerryg400
Brendan wrote:Now try to explain why programming is the only "engineering like" profession that uses text.
I think the problem is that many people who program aren't engineers.
Imagine building a bridge by starting at one side of the river and just heading toward the other side by bolting on pieces as you go. Then imagine once you've reached the other side telling everyone that this is version 0.1 of your bridge, that THIS BRIDGE IS PROVIDED BY THE BRIDGE BUILDER "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES etc. etc.
It's not really engineering. It's not really even "engineering like".
Re: Why are ASM hobby OS more successful than other language
Posted: Fri Dec 16, 2011 5:43 pm
by Rusky
Programming uses text both for historical reasons (teletypes) and because of its relationship with math, which is very text-oriented, even if it does use a lot of symbols. Text does have its advantages.