Well, I try to understand limitations in Const expressions in VBScript. I was not able to use anything except literals. What the docs say is:
Literal or other constant, or any combination that includes all
arithmetic or logical operators except Is.
So, if "that includes all arithmetic or logical operators" then logically I expect I can do something like this:
Const X = (1 + 2)
But that brings the error "Expected literal constant". I found an interesting answer here that allows one to cheat, at some level, so the above can be done with:
Execute "Const X = " & (1 + 2)
But my question is about standard constant declaration. If by chance the docs said something like "expression could be ONLY literal", then I would never ask.
So what Else I can use (besides literal)?
Script56.chm says the following in the Remarks section:
Constants are public by default. Within procedures, constants are always private; their visibility can't be changed. Within a script, the default visibility of a script-level constant can be changed using the Private keyword.
To combine several constant declarations on the same line, separate each constant assignment with a comma. When constant declarations are combined in this way, the Public or Private keyword, if used, applies to all of them.
You can't use variables, user-defined functions, or intrinsic VBScript functions (such as Chr) in constant declarations. By definition, they can't be constants. You also can't create a constant from any expression that involves an operator, that is, only simple constants are allowed. Constants declared in a Sub or Function procedure are local to that procedure. A constant declared outside a procedure is defined throughout the script in which it is declared. You can use constants anywhere you can use an expression.
The bit in italics above makes a nonsense of the "or any combination that includes all arithmetic or logical operators except Is" claim.
Related
I use this code in a testbench, which works as expected:
std_logic_vector(to_unsigned(integer(0.603205*(2**16)),16))
i want to replace it with a function defined in the same file:
function convert_mult(mult : real) return std_logic_vector is
begin
return std_logic_vector(to_unsigned(integer(mult*(2**16)),16));
end function;
and call it like this:
convert_mult(0.603205)
the function fails compilation with "Cannot find the "*" operator with operands denoted with the "[REAL, UNIVERSAL_INTEGER]" signature."
I can't work out whats wrong with this, i thought real * integer was supported? should i be using another type?
TL;DR
You can mix real and integer literals like in 0.603205*(2**16) but not non-literal reals and integer literals like in mult*(2**16). As noted by Matthew, real and integer are closely related types, so converting is easy. Use:
return std_logic_vector(to_unsigned(integer(mult*real(2**16)),16));
And, incidentally, you write I thought real * integer was supported. Well, you were wrong. It is not supported. You must use an explicit conversion... except with literals.
Details
Why does it work with literals but not with non-literals? According the VHDL 2008 Language Reference Manual (IEEE Std 1076-2008) universal_integer and universal_real are, respectively, the types of integer and floating point literals.
0.603205 is a universal_real.
2**16 is a bit more complex because it is an expression involving integer literals (universal_integers). Section 9.3.6 Type conversions of the LRM explains that universal_integer can be automatically converted to another integer type when needed by the context. I do not know exactly what automatic conversions take place because the LRM is not very easy to follow on this, but I suspect that the 16 is automatically converted to an integer according rules of section 9.3.6, which allows the use of the universal_integer ** integer operand of package STANDARD that returns a universal_integer (see section 16.3 Package STANDARD where all these operators are defined in their functional form).
Finally, section 9.5 Universal expressions explicitly states that the * operator is defined on universal_integer * universal_real and universal_real * universal_integer. Both return a universal_real.
Note: there is also a universal_real / universal_integer returning universal_real but no universal_integer / universal_real.
Every single time I load my program, even for the fist time, it says
file.rb:9: warning: already initialized constant W_mum
file.rb:6: warning: previous definition of W_mum was here.
a little help here?
W_mum = gets.to_i
elsif (W_mum = 1)
Ruby uses two different "storage bins" for data: variables and constants. In your source code, you can identify them y their first letter: constants always have a capital letter at the start of their name, variables a lower-case letter.
In your case, you thus have a constant named W_mum. Now, when you first set a value to a constant and then later set a different value to it, Ruby will show a warning (as such: you can set new values to constants, but you should not).
Now, as for why Ruby warns here: in your elsif, you are actually assigning the constant the value 1. This might be a bug though. Instead of an assignment with =, you likely intended to use a comparison here, using the == operator.
When creating a tracepoint in Visual Studio (right-click the breakpoint and choose "When Hit..."), the dialog has this text, emphasis mine:
You can include the value of a variable or other expression in the message by placing it in curly braces...
What expressions are allowed?
Microsoft's documentation is rather sparse on the exact details of what is and is not allowed. Most of the below was found by trial and error in the Immediate window. Note that this list is for C++, as that's what I code in. I believe in C#, some of the prohibited items below are actually allowed.
Most basic expressions can be evaluated, including casting, setting variables, and calling functions.
General Restrictions
Only C-style casts supported; no static_cast, dynamic_cast, reinterpret_cast, const_cast
Can't declare new variables or create objects
Can't use overloaded operators
Ternary operator doesn't work
Can't use the comma operator because Visual Studio uses it to format the result of the expression; use multiple sets of braces for multiple expressions
Function Calls
Prohibited calls:
Lambdas (can't define or call them)
Functions in an anonymous namespace
Functions that take objects by value (because you can't create objects)
Permitted calls:
Member functions, both regular and virtual
Functions taking references or pointers, to either fundamental or class types
Passing in-scope variables
Using "&" to pass pointers to in-scope variables
Passing the literals "true", "false", numbers
Passing string literals, as long you don't run afoul of the "can't create objects" rule
Calling multiple functions with one tracepoint by using multiple sets of braces
Variable Assignment
Prohibited:
Objects
String literals
Permitted:
Variables with fundamental types, value either from literals or other variables
Memory addresses, after casting: { *(bool*)(0x1234) = true }
Registers: { #eip = 0x1234 }
Use Cases
Calling functions from tracepoints can be quite powerful. You can get around most of the restrictions listed above with a carefully set up function and the right call. Here are some more specific ideas.
Force an if
Pretty straightforward: set up a tracepoint to set a variable and force an if-condition to true or false, depending on what you need to test. All without adding code or leaving the debug session.
Breakpoint "toggling"
I've seen the question a few times, "I need to break in a spot that gets hit a lot. I'd like to simply enable that breakpoint from another breakpoint, so the one I care about only gets breaks from a certain code path. How can I do that?" With our knowledge above, it's easy, although you do need a helper variable.
Create a global boolean, set to false.
Create a breakpoint at your final destination, with a condition to break only when the global flag is true.
Set tracepoints in the critical spots that assign the global flag to true.
The nice thing is that you can move the tracepoints around without leaving the debugging session. Use the Immediate window or the Watch window to reset your global flag, if you need to make another run at it. When you're done, all you need to clean up is that global boolean. No other code to remove.
Automatically skip code
The EIP register (at least on x86) is the instruction pointer. If you assign to it, you can change your program flow.
Find the address of the line you want to skip to by breaking on it once and looking at the value of EIP, either in the Registers window or the Watch window with "#eip,x". (Note that the value in the Registers window is hex, but without the leading "0x".)
Add a tracepoint on the line you want to skip from, with an expression like {#eip = address}, using the address from step 1.
EIP assignment will happen before anything on the line is executed.
Although this can be handy, be careful because skipping code like this can cause weird behavior.
As Kurt Hutchinson says, string assignment is not allowed in a tracepoint. You can get around this by creating a method that assigns the string variable, and call that.
public static class Helper
{
public static void AssignTo(this string value, out string variable)
{
variable = value;
}
}
Then in your tracepoint message:
{"new string value".AssignTo(out stringVariable)}
I'm interesting why the shorthand forms of the assignment operators only works in one way, that means appending the value of the variable.
Ex. (In Javascript):
x+=y x=x+y
x-=y x=x-y
x*=y x=x*y
x/=y x=x/y
x%=y x=x%y
Frequently I found situations where I need to prepend the variable:
Ex.
x=y+x
Suppose x and y are strings and you are concatenating.
I would like to have a syntax that allow something like:
x=+y
As I do with i++ or ++i incrementing number.
Is there some language that support this?
surely x=y+x is the same as y+=x
I'm puzzled as to why you would learn a new language just to save on 1 character!
However, I would suggest JQuery's .prepend() method
http://api.jquery.com/prepend/
There are languages that allow to define new operators and/or overload existing operators (see operator overloading).
But operators and the use of them should be unambiguous. In your example x=+y could be interpreted as x=y+x (as you denoted) but also as x=(+x) (+ as unary operation like negation operation in -1). This ambiguity can make using a language hard, especially when programmers want to make their code short and concise. That’s also why some languages don’t have syntactic sugar like pre/post increment/decrement operators (e.g. Python).
This question already has answers here:
What do ! and # mean when attached to numbers in VB6?
(3 answers)
Closed 9 years ago.
There is the following in some code I'm trying to figure out:
For I& = 1 To...
I'm not familiar with the & after a variable. What does that represent?
After some further research, it looks like the I& is being defined as a type LONG. Now my questions is why would they be doing this? Is it overkill or just legacy code?
The legacy BASIC Language had several ways of declaring variables. You could use data type suffixes ($, %, &, !, or #) to the variable name
x$ = "This is a string" ' $ defines a string
y% = 10 ' % defines an integer
y& = 150 ' & defines a long integer
y! = 3.14 ' ! defines a single
y# = 12.24 ' # defines a double
Legacy. Old-school (pre-.NET) Visual Basic used variable name suffixes in lieu of (optionally) variable types.
You are right - putting an ampersand & after a number or a variable means that it is of a Long 32-bits type.
So the answer is, how many iterations does the loop need - is it possible, that it would exceed 16 bits integer?
With no data type identifier after the i, it is implied to be of the native Integer (the default). Therefore this i is expressed as an Integer, which makes it a 16-bit i.
So, I'd say it is the original developer had this habit of explicitly stating the variable type with &, and whether it was really needed there depends on the number of iterations that the For..Next loop has to support in this case.
Most likely it is either old code ported forward to VB6 from QBasic, etc. or else just a bad habit some individual programmer had from that era. While kind of sloppy its meaning should be obvious to a VB6 programmer, since it can be used with numeric literals in many cases too:
MsgBox &HFFFF
MsgBox &HFFFF&
These display different values because they are different values.
Yes it means Long but it often reflects somebody who fails to set the IDE option to auto-include Option Explicit in new modules when created.
Using symbolic notation (Integer - %, Long - &, Single - !, Double - #, String - $) is an excellent method for variable declaration and usage. It’s usage is consistent with "structured programming" and it’s a good alternative to Hungarian notation.
With Hungarian notation, one might define a string filename as “strFileName”, where the variable name is preceded by a lower case abbreviation of the variable type. The is contrary to another good programming practice of making all global variables begin with an upper case first letter and all local variables begin with a lower case. This helps the reader of your code instantly know the scope of a variable. Ie. firstName$ is a local string variable; LastName$ is a global string variable.
As with all programming, it’s good to follow conventions, ..whether you define your own conventions or somebody else’s conventions or industry conventions. Following no conventions is a very poor programming practice. Using symbolic notation is one type of naming convention.