I'm currently writing an interpreter for a simple programming language and just wanted to ask on the best approach would be to tackle it.
The environment for a program is as follows:
type Env = [[(Var, Int)]]
So I've coded the lookup and update but I'm a bit stuck on how to deal with the the scope for each begin block. An example is shown below:
begin [a,b,c]
read i
n = 1
while i < 0 do
begin
n = 2 * n
i = i - 1
end;
write n
end
From my understanding the scope of the first begin would be [a,b,c,i,n]
and then the second begin would contain [i, n]
therefore the env would be
[ [ ("a",0), (b",0), ("c",0), ("i",3), ("n",2) ], [("n",8), ("i",0) ] ]`
Currently my lookup function returns the first occurrence of a variable, so I'm having problems with the 2nd scope (2nd begin).
I'm not quite sure how I can make the update and lookup function return the value associated with that particular scope.
Basically I have the code working for one begin statement, but I am having issues with 2 or more statements in the sample program.
Related
Our professor gave us this skeleton for a case statement, and so far no one is able to understand what it's doing.
always#(*)
begin
case(state)
3'b000:{nout, nstate} = (in)?(in=1):(in=0)
endcase
end
More insight:
This is being implemented as a button debouncer.
nout is the output of the next state: a single bit
nstate is the next state: 3 bits
in is also 1 bit wide
My understanding is that the concatenation operator will append nout to nstate resulting in 4 bits. (ie: if nout is 1 and nstate is 010, this part of the statement will produce 1010)
On the other side of the equality assignment we have a simple comparator, which upon further inspection, doesn't seem to do anything...
It's basically saying
if(in == 1) {
in = 1;
} else {
in = 0;
}
With that understanding, we're assigning a single bit to nout and nstate?
This understanding doesn't make any sense to me. I've compared my notes with 2 other classmates whom wrote the exact same thing so I'm thinking either we don't understand the code or there's an error.
Further insight:
Upon researching further, I've found the state diagram appear in multiple places, which makes me fairly confident that this is a common Moore Machine.
i hope that you did not cut and paste those expressions correctly.
3'b000:{nout, nstate} = (in)?(in=1):(in=0);
The above statement is a complete mess. Most likely it will fail any linting. It might be ok syntactically, but makes no sense logically and makes such code unreadable and not maintainable. It has to look like the following:
3'b000:{nout, nstate} = (in)?(1'b1):(1'b0);
The left hand side concat represents a signal with lower 3 bit associated with nstate, and upper n bits with nout. The right hand side ternary operator produces either one bit '1' or 1 bit '0' (actually id does the same int the original expression, because 'in' is 1 bit wide. Verilog will extend the rhs one bit to the size of the lhs and add missing '0's. As a result nout will be 0 and nstate will be either 3'b000 or 3'b001, depending on the value of in.
I understand that, for 2 always blocks with the same trigger, their order of evaluation is completely unpredictable.
However, suppose I have:
always #(a) begin : blockX
c = 0;
d = a + 2;
if(c != 1) e = 2;
end
always #(a) begin : blockY
e = 3;
end
always #(d) begin : blockZ
c = 1;
e = 1;
end
Suppose block X evaluates first. Does changing d in blockX immediately jump to blockZ? If not, when is blockZ evaluated with respect to blockY?
My programmer's instinct thinks of the sequence of events as a stack, where evaluating blockX is like a function call to blockZ and I immediately jump there in the code, then finish evaluating blockX.
However, because we call the active events queue, well, a queue, this suggests blockZ is enqueued at the back of the active events queue, and I'm 100% guaranteed it will be evaluated last (unless there are other triggered always blocks).
There's also the intermediate possibility, where it's neither first nor last but is also evaluated in a random and unpredictable order.
So in this example, are 1, 2, or 3 all possible final values for e, depending on how the compiler is feeling at run time?
Additionally, while I understand, of course, this represents awful style, where might I find the specification for this kind of behvaior?
Always blocks are not function calls. See a recent answer I just gave for a similar question. These blocks are concurrent processes. The LRM only guarentees the ordering of statements within a begin/end block. There is no defined ordering between concurrently executing begin/end blocks (See Section 4.7 Nondeterminism in the 1800-2012 LRM) So a simulator is free to interleave the statements in any way as long as it honors the order within a single block.
So you are correct that e could have the final values 1, 2 or 3 depending on how a simulator decides to implement and optimize your code.
I encountered a confusion , when i pass a variable x to variable y by reference then both x and y should now point to same location, but the output that i am getting is not same.
Full detail discussion is here: http://gateoverflow.in/94182/programming-output
I have tried my best to explain the stuff to user but i am still unable to convience him fully, maybe i am lacking some concept.
rough code sample:
var b : int;
procedure M (var a, int)
begin
a= a*a;
print(a);
end;
procedure N
begin
b= b+1;
M(b);
end;
begin
b=12;
N;
print(b);
end;
I assume that as in question it is given that variables are static , so the value of a b should not change from 13 , but the value of a should be 13*13=169 , but my reasoning is counter to what call by reference is about.
pascal code from unauthorized book, please throw some insights.
I had to review scoping terminology. I had myself confused between static and dynamic scoping. Static scoping is used in all modern programming languages. I conclude that both a and b should have a value of 169 at the respective print statements.
In perl there are hashes, key-value pairs. Does Isabelle/HOL have a builtin such function with the corresponding theorems?
Typically in Isabelle/HOL, you would just use a function of type 'key ⇒ 'value. For instance:
definition "num_animals
≡ (λ_. 0)(''dog'' := 3, ''cat'' := 42, ''mouse'' := 12)"
lemma "num_animals ''dog'' = 3"
by (simp add: num_animals_def)
Here, (λ_. 0) is a function that returns 0 for all input values, while the syntax (''dog'' := 3) modifies the existing function so that the input dog returns 3.
If you want to be able to determine if a function does not contain a particular key, you can use Isabelle/HOL's option type:
definition "num_animals
≡ (λ_. None)(''dog'' := Some 3, ''cat'' := Some 42, ''mouse'' := Some 12)"
lemma "num_animals ''elephant'' = None"
by (simp add: num_animals_def)
There are numerous differences between this and a hash-table. For example, Isabelle will have to perform at least O(n) steps to look up a value in the function in this format. Also, no hashing is going on: key values are stored and compared explicitly. Usually, though, because you are reasoning about these things, and not typically trying to execute these things, this is not a problem.
If you are dealing with larger proof terms, you may need to look into other representations of functions, such as Binary Search Trees in the AFP, though these will be harder to work with.
I am trying to compare two strings in Smalltalk, but I seem to be doing something wrong.
I keep getting this error:
Unhandled Exception: Non-boolean receiver. Proceed for truth.
stringOne := 'hello'.
stringTwo := 'hello'.
myNumber := 10.
[stringOne = stringTwo ] ifTrue:[
myNumber := 20].
Any idea what I'm doing wrong?
Try
stringOne = stringTwo
ifTrue: [myNumber := 20]`
I don't think you need square brackets in the first line
Found great explanation. Whole thing is here
In Smalltalk, booleans (ie, True or False) are objects: specifically, they're instantiations of the abstract base class Boolean, or rather of its two subclasses True and False. So every boolean has type True or False, and no actual member data. Bool has two virtual functions, ifTrue: and ifFalse:, which take as their argument a block of code. Both True and False override these functions; True's version of ifTrue: calls the code it's passed, and False's version does nothing (and vice-versa for ifFalse:). Here's an example:
a < b
ifTrue: [^'a is less than b']
ifFalse: [^'a is greater than or equal to b']
Those things in square brackets are essentially anonymous functions, by the way. Except they're objects, because everything is an object in Smalltalk. Now, what's happening there is that we call a's "<" method, with argument b; this returns a boolean. We call its ifTrue: and ifFalse: methods, passing as arguments the code we want executed in either case. The effect is the same as that of the Ruby code
if a < b then
puts "a is less than b"
else
puts "a is greater than or equal to b"
end
As others have said, it will work the way you want if you get rid of the first set of square brackets.
But to explain the problem you were running into better:
[stringOne = stringTwo ] ifTrue:[myNumber := 20]
is passing the message ifTrue: to a block, and blocks do not understand that method, only boolean objects do.
If you first evaluate the block, it will evaluate to a true object, which will then know how to respond:
[stringOne = stringTwo] value ifTrue:[myNumber := 20]
Or what you should really do, as others have pointed out:
stringOne = stringTwo ifTrue:[myNumber := 20]
both of which evaluates stringOne = stringTwo to true before sending ifTrue:[...] to it.
[stringOne = stringTwo] is a block, not a boolean. When the block is invoked, perhaps it will result in a boolean. But you are not invoking the block here. Instead, you are merely causing the block to be the receiver of ifTrue.
Instead, try:
(stringOne = stringTwo) ifTrue: [
myNumber := 20 ].
Should you be blocking the comparison? I would have thought that:
( stringOne = stringTwo ) ifTrue: [ myNumber := 20 ]
would be enough.
but I seem to be doing something wrong
Given that you are using VisualWorks your install should include a doc folder.
Look at the AppDevGuide.pdf - it has a lot of information about programming with VisualWorks and more to the point it has a lot of introductory information about Smalltalk programming.
Look through the Contents table at the beginning, until Chapter 7 "Control Structures", click "Branching" or "Conditional Tests" and you'll be taken to the appropriate section in the pdf that tells you all about Smalltalk if-then-else and gives examples that would have helped you see what you were doing wrong.
I would like to add the following 50Cent:
as blocks are actually lambdas which can be passed around, another good example would be the following method:
do:aBlock ifCondition:aCondition
... some more code ...
aCondition value ifTrue: aBlock.
... some more code ...
aBlock value
...
so the argument to ifTrue:/ifFalse: can actually come from someone else. This kind of passed-in conditions is often useful in "..ifAbsent:" or "..onError:" kind of methods.
(originally meant as a comment, but I could not get the code example to be unformatted)