Why does Forth reserve two cells per variable? - forth

While trying to find out how Forth manages the dictionary (and memory in general), I came across this page. Being familiar with C, I have no problem with the concept of pointers, and I assume I understood everything correctly. However, at the end of the page are several exercises, and here I noticed something strange.
Exercise 9.4, assuming DATE has been defined as a VARIABLE, asks what the difference is between
DATE .
and
' DATE .
and exercise 9.5 does the same using the user variable BASE.
According to the supplied answers, both phrases will give the same result (also with BASE). Trying this with Win32Forth however, gives results with a difference of 4 bytes (1 cell). Here is what I did:
here . 4494668 ok
variable x ok
x . 4494672 ok
' x . 4494668 ok
Creating another variable gives a similar result:
variable y ok
y . 4494680 ok
' y . 4494676 ok
Thus, it looks like each variable gets not just one cell (for the value), but two cells. The variable itself points to where the actual value is stored, and retrieving the contents at the execution token (using ' x ?) gives 0040101F for both variables.
For exercise 9.5, my results are:
base . 195F90 ok
' base . 40B418 ok
These are not even close to each other. The answer for this exercise does however mention that the results can depend on how BASE is defined.
Returning to normal variables, my main question thus is: why are two cells reserved per variable?
Additionally:
Since only one cell contains the actual value, what do the contents of the other cell mean?
Is this specific to Win32Forth? What happens in other implementations?
Is this different for run-time and compile-time variables?
How do answers to the above questions apply to user variables (such as BASE)?
EDIT1: Okay, so Forth also stores a header for each variable, and using the ' gives you the address of this header. From my tests I would then conclude the header uses just one cell, which does not correspond to all the information the header should contain. Secondly, according to the exercise retrieving the address of a variable should for both cases give the same result, which appears to contradict the existence of a header altogether.
My gut feeling is that this is all very implementation-specific. If so, what happens in Win32Forth, and what should happen according to the exercise?

This is roughly how a definition looks like in the dictionary using a traditional memory layout. Note that implementations may well diverge from this, sometimes a lot. In particular, the order of the fields may be different.
Link to previous word (one cell)
Flags (a few bits)
Name length (one byte, less a few bits)
Name string (variable)
Code field (one cell)
Parameter field (variable)
Everything except the code and parameter fields is considered the header. The code field usually comes right before the parameter field.
Ticking a word with ' gives you an XT, or execution token. This can be anything the implementation fancies, but in many cases it's the address of the code field.
Executing a word created with CREATE or VARIABLE gives you the address of the parameter field.
This is probably why in Win32Forth, the two addresses differ by 4 bytes, or one cell. I don't know why the answers to the exercises state there should be no difference.
Assuming BASE is a user variable, it probably works like this: Every task has its own user area in which user variables are allocated. All user variables know their specific offset inside this area. Ticking BASE gives you its XT, which is the same for all tasks. Executing BASE computes an address by adding its offset to the base of the user area.

Related

How can I combine these 2 functions without going over the 50,000 character limit?

I tried to simply replace anytime I referenced the cell into the actual function inside of the referred cell. This normally works in every single other function
I've done this with, but in this case, it's a big function and it gets referred to many times. This causes it to go over the 50,000 character limit for functions and this method no longer applies.
check out this spreadsheet to see the functions I'm talking about:
https://docs.google.com/spreadsheets/d/1RFA8s68TSQI2jQSOQm2_Ma776vC1LUQn7JP9tg-gZ1g/edit?usp=sharing
here's the formula:
=index(fixed(regexextract(A3,"[\d.]+")*product(10^vlookup(regexextract(A3,regexreplace(A3,"([A-Za-z])","($1)")),split(flatten(regexextract(flatten(split("Kk,Mm,Bb,Tt,q,Q,s,S,Oo,Nn,d,Uu,D",",")),regexreplace(flatten(split("Kk,Mm,Bb,Tt,q,Q,s,S,Oo,Nn,d,Uu,D",",")),"(.)","($1)"))&"❄️"&sequence(13,1,3,3)),"❄️"),2,0))/(2.5*B3+1)/10^sumproduct((exact(index(split(flatten(regexextract(flatten(split("Kk,Mm,Bb,Tt,q,Q,s,S,Oo,Nn,d,Uu,D",",")),regexreplace(flatten(split("Kk,Mm,Bb,Tt,q,Q,s,S,Oo,Nn,d,Uu,D",",")),"(.)","($1)"))&"❄️"&sequence(13,1,3,3)),"❄️"),,1),C3))*(index(split(flatten(regexextract(flatten(split("Kk,Mm,Bb,Tt,q,Q,s,S,Oo,Nn,d,Uu,D",",")),regexreplace(flatten(split("Kk,Mm,Bb,Tt,q,Q,s,S,Oo,Nn,d,Uu,D",",")),"(.)","($1)"))&"❄️"&sequence(13,1,3,3)),"❄️"),,2))),D3)&C3)
I couldn't find an efficient way to automatically convert back to the best unit because we are dealing with huge numbers that get turned to scientific notation preventing us from easily getting the actual length of the number. For this reason, I added a cell (C3) where you can specify the unit you want. I also added another cell (D3) where you can specify the amount of decimal places you want to display.

Trying to understand this profiling result from F# code

A quick screenshot with the point of interest:
There are 2 questions here.
This happens in a tight loop. The 12.8% code is this:
{
this with Side = side; PositionPrice = position'; StopLossPrice = sl'; TakeProfitPrice = tp'; Volume = this.Volume + this.Quantity * position'
}
This object is passed around a lot and has 23 fields so it's not tiny. It looks like immutability is great for stable code, but it's horrible for performance.
Since this recursive loop is run in parallel, I need to store it's context variables in an object.
I am looking for a general idea of what makes sense, not something specific to that code because I have a few tight loops with a bunch of math which I need to profile as well. I am sure I'll find the same pattern in several places.
The flaw here is that I store both the context for the calculations and its variables in a singe type that gets passed in the loop. As the variable fields get updated, the whole object has to be recreated.
What would make sense here (in general for this type of situations)?
make the fields that can change mutable. In this case, that means keeping the type as is (23 fields) and make some fields mutable (only 5 fields get regularly changed)
move the mutable fields to their own type to have a general context object and one holding all the variables. In this case, that means having a context with (23 - 5 fields) and a separate 5 fields type
make the mutable fields variables and move them out of the type. In this case, these 5 fields would be passed as variables in the recursive loop?
and for the second question:
I have no idea what the 10.0% line with get_Tag is. I have nothing called 'Tag' in the code, so I assume that's a dotnet internal thing.
I have a type called Side and there is a field with the same name used in the loop, but what is the 'Tag' part?
What I would suggest is not to modify your existing immutable type at all. Instead, create a new type with mutable fields that is only used within your tight loop. If the type leaves that loop, convert it back to your immutable type (assuming you don't need a copy to go through the rest of your program with every iteration).
get_Tag in this case is likely the auto-generated get-only property on a discriminated union, it's just how the F# compiler represents this sort of type in CLR. The property can most easily be seen when looking at F# code from C#, here's a great page on F# decompiled:
https://fsharpforfunandprofit.com/posts/fsharp-decompiled/#unions
For the performance issues I can only offer some suggestions:
If you can constrain the context object to your code only, then try making a mutable version and see which effect it has.
You mention that the context object is quite large, is it possible to split it up?

Filemaker if dropdown contains text alter calculation

I am fairly sure stuff like this has been answered but I am losing my hair at the moment with this. I am using Filemaker Pro 13
I have been landed with the job of updating some templates, I have done this before but all I was doing was updating the visual side of things. Now I am wanted to dynamically update some labels and calculations depending on a 'Company selected(drop down with custom values that are all text).
Currently all costs are multiplied by 2. So if original cost = $4 then customer cost is $8. However if 'Company 4' is selected rather than being multiplied by 2 it needs to be multiplied by 1.5.
I currently have two functions that I am trying to use this functionality on a field box.
First function:
If (Company: = "Comp4"; 1;0)
Second function:
If (${Function1}; ${$Cost}*1.5; ${$Cost}*2 )
This does not work, hence the answering of this question. As far as I could understand if statements work as (Condintion; If true do X; Else do Y;). This may be the problem? I do come from a programming background but this program is irritating me beyond belief at the moment.
If this has been answered before then I offer my sincerest apologies.
Thank you for any answers or help pointing me into the right direction.
Edit: Just tried this:
If (ValueCount(FilterValues(Company;"Comp4"));${$Cost}*1.5; ${$Cost}*2)
This was to no avail. Ideally if I could fit this into one function that would be great but so far I am still failing.
Edit 2:
With regards to the function / functions not working. I would often only get the ${$Cost}*2 side of things would happen however the ${$Cost}*1.5 would not even when "Comp4" was selected. This made me think that it was either the system was not detecting "Comp4" was selected or I need to look elsewhere to find the value I need to look at.
Edit 3: Real values and calculations used
Currently used and working so to speak ( Just does the *2 aspect of things)
Field Name: x2$Charges
Calculation: ${$Charges}*2. - $Charges is the 'cost' fields (10 of them).
What I want to do is when a specific company is selected rather than doing cost *2 I want to do cost *1.5.
The check for said company is :
Field Name: x2CheckSSL
Calculation: If(Sales Rep.|Distributor: = "SSL";1.5;2)
Where Sales Rep.|Distributor: is 'Company'
It's difficult to tell what is wrong with your syntax, because we don't know the exact names of your fields. Also, "this does not work" is not a good description of a problem.
The fact that you have constructs like ${$Cost} indicates that you have invalid field names.
If you had fields named Company and Cost, then a calculation field (defined in the same table as these two fields) =
If ( Company = "Comp4" ; 1.5 ; 2 ) * Cost
should provide the expected result.
On a more general level, this is not a good approach to take. All of these factors {"Comp4", 1.5, 2} are data and should not be hard-coded into a calculation formula.
Properly, every company should have a markup value stored in its own record, and this would be looked up into a field when you select a company. Alternatively, only some (preferred) companies would have a markup, while others would use a default value stored in a preferences table.
In addition, the Company field in this table (Invoices?) should really be CompanyID and store only the (meaningless) ID of the selected company.
Added:
This is a suggestion how to perform a quick fix to your current problem, following the clarifications made in comments.
The following fields are being assumed:
• $Charges - Number[10]
• Sales Rep.|Distributor: - Text
• x2$Charges - Calculation[10] = [see formula below]
Change the calculation formula of x2$Charges to =
If ( Extend (Sales Rep.|Distributor: ) = "SSL" ; 1.5 ; 2 ) * ${$Charges}
There is no need for the x2CheckSSL field.
IMPORTANT:
You should not use repeating fields for this. I suggest that as soon as possible you rewrite your solution and fix the flaws dscovered here, namely:
Rename your fields to valid (and reasonable*) names ;
Convert repeating fields to records in a related table;
Use lookups instead of hard-coding data in calculations.
(*) e.g. not names that end with ":"
IF statement works exactly as you described and I do not see why you need two different functions. I do not understand your syntax - ${$Cost}. Are you trying to add "$" to your output?
Let's say you have a field for selection as "slelect_company" in Companies table/layout and you stored cost in a variable called $cost
You calculation will be:
If (Companies::slelect_company = "Comp4"; $Cost*1.5; $Cost*2 )
If you set the field to output result, use formatting to add $ sign
If you set the label on the layout to show the output, use this:
If (Companies::slelect_company = "Comp4"; "$" & $Cost*1.5; "$" & $Cost*2 )
If you have more than one check, you can use Case - similar to switch in the other languages
Rather than putting your calculation in a function try creating a new calculation field and put your calculation there. When the record is committed you will see the value of this calculation field change and you will know if your function is working.
To do this
Go to File->Manage->Database
Type in a new field name and select "calculation" as the type and press create.
Enter your calculation e.g. if(Companies::select_company = "Comp4"; Companies::Cost * 1.5; Companies::Cost * 2)
The calculation engine will tell you what the errors are when you try to press okay after typing the calculation.
If it never detects the condition "Comp4" then there is an error in your string comparison, perhaps a trailing space, or an uppercase character or similar.

When do FORTRAN subprograms save data, and when not?

Have a pretty simple function for taking the name of a month, "Jan", "Feb", etc. and converting to the number of the month:
function month_num(month_str)
character*(*) :: month_str
character*3 :: month_names(12)
integer :: ipos(1),location(12)
data month_names/'Jan','Feb','Mar','Apr','May','Jun','Jul','Aug', &
'Sep','Oct','Nov','Dec'/
where (month_names==month_str) location=1
ipos = maxloc(location)
month_num = ipos(1)
end function
And OK, yes, I know it's dangerous to not define "location" before using it.
Problem: During execution of the function, if input is OK, some value of "location" will be set to 1. And, to my surprise, when the function is called again, that value will still be equal to 1. And this, of course, really messes things up. So I figured I would fix it with a new line
data location/12*0/
And I got the same problem.
Finally, I put in
location = 0
just before the "where" statement, and that fixed everything.
So, I thought FORTRAN subprograms would not save data unless the variables were declared with the "SAVE" attribute. Also, with many compilers, you can invoke some sort of "static" option that will keep everything saved. I did neither of these here, but the "location" array was saved just the same. Can someone enlighten me on the rules of when FORTRAN saves data and when not? Thanks.
The value of a variable local to a procedure is preserved across (ie it is SAVEd) in one of two ways:
The programmer specifies the SAVE attribute when declaring the variable, for example:
REAL, SAVE :: var1
The programmer initialises the variable upon declaration, for example
REAL :: var1 = 3.1415
This second, implicit, behaviour is one features of Fortran which seem designed to catch out the programmer, and not just beginners. Note that the value the variable has upon re-invocation is not, in the 2nd example 3.1415, but whatever value it had when the last invocation exited.
It is common for compilers to behave as if a variable is SAVEd when the programmer has not exercised either of these options, perhaps the memory locations used by one invocation of a procedure are not overwritten before the next invocation. But this behaviour is not to be relied on.
The situation is slightly different for variables declared in modules. Again any variable with the SAVE attribute is saved but any other variable only retains its value while the module is use-associated with a program unit which has started executing but not finished. Again some compilers, and some executions of some programs, may behave as if the value of a module variable is preserved despite the module going out of scope but this is non-standard behaviour and not to be relied on.
This behaviour is scheduled to change in Fortran 2008 when variables defined in modules will acquire the SAVE attribute implicitly.
Personally I like to explicitly SAVE variables even when I am sure that they would get the attribute implicitly, it makes the code just a bit easier to understand next time round.

Obtain original (unexpanded) macro text using libclang

Using libclang, I have a cursor into a AST, which corresponds to the statement resulting from a macro expansion. I want to retrieve the original, unexpanded macro text.
I've looked for a libclang API to do this, and can't find one. Am I missing something?
Assuming such an API doesn't exist, I see a couple of ways to go about doing this, both based on using clang_getCursorExtent() to obtain the source range of the cursor - which is, presumably, the range of the original text.
The first idea is to use clang_getFileLocation() to obtain the filename and position od the range start and end, and to read the text directly from the file. If I've compiled from unsaved files then i need to deal with that, but my main concern with this approach is that it just doesn't seem right to be going outside to the filesystem when I'm sure clang holds all this information internally. There also would be implications if the AST has been loaded rather than generated, or if the source files have been modified since they were parsed.
The second approach is to call clang_tokenize() on the cursor extent. I tried doing this, and found that it fails to produce a token list for most of the cursors in the AST. Tracing into the code, it turns out that internally clang_tokenize() manipulates the supplied range and ends up concluding that it spans multiple files (presumably due to some effect of the macro expansion), and aborts. This seems incorrect to me, but I do feel that in any case I'm abusing clang_tokenize() trying to do this.
So, what's the best approach?
This is the only way I've found.
So you get the top level cursor with clang_getTranslationUnitCursor(). Then, you do clang_visitChildren(), with the visitor function passed into this returning CXChildVisit_Continue so that only the immediate children are returned. Among the children, you see the usual cursor types for top level declarations (like CXCursor_TypedefDecl, CXCursor_EnumDecl) but among them there's also CXCursor_MacroExpansion. Every single macro expansion appears to show up in a cursor with this type. You can then call clang_tokenize() on any of these cursors and it gives you the unexpanded macro text.
I have no idea why macro expansions get stuck near the top of the AST instead of within elements where they get used, it makes things pretty awkward. Example:
enum someEnum{
one = SOMEMACRO,
two,
three
}
It'd be nice if the macro expansion cursor for SOMEMACRO were within the enum declaration instead of being a sibling to it.
(I realize this is ridiculously late but I'm hoping this gets libclang more exposure, maybe someone more experienced with it can provide more insight).

Resources