Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.
|
Forum Index : Microcontroller and PC projects : Error: Variable type not specified...
Page 1 of 2 | |||||
Author | Message | ||||
Grogster Admin Group Joined: 31/12/2012 Location: New ZealandPosts: 9056 |
This one has me beat. At start of code: DIM INTEGER RX, Y Open "COM1:1200" as #1 'COM port to HC12 in FU4 mode Open "COM2:2400" as #2 'COM port to NRX2 data filter Note I am defining variable RX as an integer. In my main loop I have a line: DECODE(1) 'Decode and display the data packet The number for the argument can be either 1 or 2, and is simply to tell the DECODE sub, what COM port to suck data out of for the decode routine. The DECODE sub is: SUB DECODE(RX) Pause 150 'Delay to allow all of message to arrive in buffer P$=INPUT$(LOC(RX),RX) ... End Sub I have not posted the whole sub, as it falls over on the very first line with the error message: (90) Sub DECODE(RX) Error: Variable type not specified ...but I specified it as an integer variable at the top of the code. I've made subs with arguments work fine before, so I don't understand what I am doing wrong. Parenthesis around line number 90 instead of square brackets, just cos the forum code will try to react to the square brackets. MicroMite 2 on 170 chip, version 5.0501 I tried writing a really simple experiment: DECODE(5) END SUB DECODE(RX) Print RX END SUB ...and that works as expected - prints a 5 on the console. My first code will not even accept the RX argument. Anyone got any ideas what I am doing wrong? Edited 2022-12-15 20:03 by Grogster Smoke makes things work. When the smoke gets out, it stops! |
||||
thwill Guru Joined: 16/09/2019 Location: United KingdomPosts: 3833 |
Presumably you have OPTION EXPLICIT set ? Looks like you declared a global variable RX to be an INTEGER, you've said nothing about the type of the sub parameter called RX. Best wishes, Tom Edited 2022-12-15 20:05 by thwill Game*Mite, CMM2 Welcome Tape, Creaky old text adventures |
||||
JohnS Guru Joined: 18/11/2011 Location: United KingdomPosts: 3649 |
+1 You have both a global RX and a local (parameter) RX - but the latter's type is unspecified so will determined by such as your other settings / default(s). For readable code you probably don't want to reuse like that, even if you sort out the type :) John |
||||
Grogster Admin Group Joined: 31/12/2012 Location: New ZealandPosts: 9056 |
OPTION EXPLICIT OPTION DEFAULT NONE. I think the 2nd option is the problem. I just disabled it, and everything is working as expected.... Those two options are automatically added to the top of the code by MMEDIT when I started a new code. This seems to be the root cause of the issue. Perhaps someone can help me understand why DEFAULT NONE would upset things. Manual states for OPTION DEFAULT: "If OPTION DEFAULT NONE is used, then all variables must have their type explicitly defined." - which is what I thought I was doing with DIM INTEGER RX.... In any event, things are working fine now, but I would love to understand why the option was causing this, cos I am confused now with OPTION DEFAULT NONE meaning you have to explicitly define variable types, so I do - and it stops with an error saying I haven't.... Smoke makes things work. When the smoke gets out, it stops! |
||||
Grogster Admin Group Joined: 31/12/2012 Location: New ZealandPosts: 9056 |
Now I'm even more confused. RX is a variable I am using to pass the value of 1 or 2 to the DECODE sub. Specify the variable value via the command: DECODE(1) Pass that value to the sub via RX: SUB DECODE(RX) Use the value of RX inside the sub - which is now 1, but if I used DECODE(5), then RX inside the sub would be 5. All this is borrowed from using strings like that, for example, having an ERRORS sub: SUB ERRORS(D$) Print "An error occurred: "+D$ END SUB ...and call it with ERRORS("You did something wrong.") It is likely that I might be doing something fundamentally wrong here - would not be the first time - but it has worked up till now, and is working again just fine once I disabled the OPTION DEFUALT NONE line. Would love to understand what I have wrong and why, so feel free to comment! Smoke makes things work. When the smoke gets out, it stops! |
||||
thwill Guru Joined: 16/09/2019 Location: United KingdomPosts: 3833 |
Hi @Grogster, Despite you having given them the same name there is no relationship (except in your head) between the RX global variable (declared using DIM) and a FUNCTION/SUB "parameter" or LOCAL "variable" called RX. You need to specify the type of the RX parameter to the SUB independently: OPTION DEFAULT NONE OPTION EXPLICIT ON DIM INTEGER RX, Y ' <-- You don't actually need to declare RX if you ' aren't using it globally. Open "COM1:1200" as #1 'COM port to HC12 in FU4 mode Open "COM2:2400" as #2 'COM port to NRX2 data filter ... DECODE(1) 'Decode and display the data packet ... SUB DECODE(RX AS INTEGER) ' <-- Changed here Pause 150 'Delay to allow all of message to arrive in buffer P$=INPUT$(LOC(RX),RX) ... END SUB This is fine. SUB ERRORS(D$) is an alternative way of writing SUB ERRORS(D AS STRING), so you are providing the D parameter with a type unlike the RX parameter. Strictly speaking it isn't working "fine", with that line disabled the RX parameter will be a FLOAT not an INTEGER which in most cases will work. Best wishes, Tom Edited 2022-12-15 20:43 by thwill Game*Mite, CMM2 Welcome Tape, Creaky old text adventures |
||||
Grogster Admin Group Joined: 31/12/2012 Location: New ZealandPosts: 9056 |
Excellent - thank you Tom. All this time, I did actually have it wrong for integers then, cos I was borrowing from the ERRORS kind of sub that worked. Assumptions are the mother of all.....well - you all probably know the rest of that line. I will make the changes, and thanks again - you have helped to clarify it. Smoke makes things work. When the smoke gets out, it stops! |
||||
thwill Guru Joined: 16/09/2019 Location: United KingdomPosts: 3833 |
No worries. Note if you didn't realise it already you can write this to declare the parameter type as an INTEGER: SUB DECODE(RX%) Pause 150 'Delay to allow all of message to arrive in buffer P$=INPUT$(LOC(RX%),RX%) ... END SUB or if you want to explicitly use FLOATs: SUB DECODE(RX!) Pause 150 'Delay to allow all of message to arrive in buffer P$=INPUT$(LOC(RX!),RX!) ... END SUB Though if using this syntax (which I do "religiously") you need to consistently use the $, % or ! suffix whenever you refer to that particular variable or parameter. Best wishes, Tom Edited 2022-12-15 20:55 by thwill Game*Mite, CMM2 Welcome Tape, Creaky old text adventures |
||||
Grogster Admin Group Joined: 31/12/2012 Location: New ZealandPosts: 9056 |
Lovely, thanks - I have made the changes(using RX% in the sub), and put back in the OPTION DEFAULT NONE at the top of the code, and everything is perfect now. My suspicion was correct - I had it fundamentally wrong! I'm actually rather shocked and surprised that I have been using MMBASIC for so long, and never really had this issue before. I guess it is cos GENERALLY SPEAKING, my codes are not that complicated, and I tend to use subs with no arguments at all, and so they always work. I always use $ for strings, and have from the days of Atari BASIC back in the 80's, so I will have to remember to use the % symbol for integers moving forward! Smoke makes things work. When the smoke gets out, it stops! |
||||
Tinine Guru Joined: 30/03/2016 Location: United KingdomPosts: 1646 |
Hey Graeme, I had a similar problem, a few years ago and a solution from here wasn't forthcoming. I eventually found that the most reliable way was to not replicate variable names that are passed. As far as the sub/function is concerned, the parameters are only place-holders for whatever data-type....right? Craig |
||||
Mixtel90 Guru Joined: 05/10/2019 Location: United KingdomPosts: 5707 |
Agreed, Craig. I like to make the placeholder variables explanatory if possible. It's a lot less confusing to me. Mick Zilog Inside! nascom.info for Nascom & Gemini Preliminary MMBasic docs & my PCB designs |
||||
JohnS Guru Joined: 18/11/2011 Location: United KingdomPosts: 3649 |
A parameter is a bit like a LOCAL in that both in effect hide any global with the same name. That happens as long as the parameter/local is in effect (so, the whole of the "lexical scope" of the SUB / FUNCTION). Well-written code typically uses few if any globals so this is not usually a problem. (Short test programs may well be an exception.) By "lexical scope" I mean the body of the sub/function, i.e. what occurs as your eye sees it between its start & end (i.e. it doesn't include anything called by it; whatever those may be would each have their own lexical scopes). Some languages don't let you reuse a name this way, i.e. you'd get an error. John |
||||
CaptainBoing Guru Joined: 07/09/2016 Location: United KingdomPosts: 1985 |
... or don't use global variable names as the alias in Sub/Function definitions As an aside; MMBasic parses variable names 32 bits (4 chars) at a time. From playing in VARTABLE, I have noted that if the type of the variable is specified, a character for it is taken up in the name - even though there is a "type byte" in the variable header which is not part of the name (or even near it or %, ! or $). So This parses minutely faster than That% (it matters in counting loops where you might get rapidly into the thousands) you can see this 32 character thing for yourself if you try to define a variable with 32 character name, then do the same with a type indicator. It breaks. Remove one character (so now it's 31 chars long) and you can specify the type. The above might seem convoluted and difficult to follow, but in short don't use specific type in variable names unless you want to. I agree strings should always have a $ (it's the law!) but I tend to default everything to integers otherwise (yes floats get a !) this way the most common variable type gets parsed the quickest. I am a pedant, but it matters. Edited 2022-12-16 00:09 by CaptainBoing |
||||
Bleep Guru Joined: 09/01/2022 Location: United KingdomPosts: 409 |
Hi Grogster, You can also use the AS format for declaration, so SUB DECODE(RX AS Integer) Then you don't need to keep appending the $ % ! when you use the variable in the subroutine. Regards Kevin. |
||||
thwill Guru Joined: 16/09/2019 Location: United KingdomPosts: 3833 |
Note that I believe this matters considerably less in CMM2, MMB4W and PicoMite versions of MMBasic than the earlier 'mite iterations because the former use hash-table lookup (rather than linear lookup) of variable names and thus have to compare strings significantly fewer times on each variable lookup. Let's just say I regularly use very long variable names (though admittedly loop iterators tend to be i%, j%, k%) and haven't had to worry about it yet except on the CMM1. Best wishes, Tom Edited 2022-12-16 00:45 by thwill Game*Mite, CMM2 Welcome Tape, Creaky old text adventures |
||||
CaptainBoing Guru Joined: 07/09/2016 Location: United KingdomPosts: 1985 |
agreed. I was coming from a Mk2 perspective (my main fodder). In my defence, I know Grogs uses loads of them too... pretty thin but it's all I got. As I note in my itch-scratch page on FotS " Not much of the following really applies to ... modern CPUs but there are elements of "sanitary" code development that will make you feel warm and fuzzy all over. It is worth mentioning that modern code suffers from a phenomenon colloquially known as "bloat" - this is largely the effect of developers not writing compactly (or even sloppily) because they don't have to care in these days of immensely fast multi-core CPUs and gigabytes of memory. Am I being too hard on them? Perhaps. In the days of slower systems, you could write something and see that it just wasn't good enough and so you'd have several stabs at it each time getting better (hopefully). Modern machines are so fast that even garbage runs in a twinkle so maybe developers don't get that kick in the pants when something they have written clearly runs like a three-legged donkey ... Personally, I get a buzz out of making code as good as I think I can get it, maybe revisiting code months later just for the mental exercise... Old habits and all that. " what can I say, I am a dinosaur Edited 2022-12-16 01:08 by CaptainBoing |
||||
Tinine Guru Joined: 30/03/2016 Location: United KingdomPosts: 1646 |
No, you are not. I couldn't agree more Craig |
||||
Mixtel90 Guru Joined: 05/10/2019 Location: United KingdomPosts: 5707 |
I pointed out as much on my Nascom website quite some time ago! Volhout's PIO course is like a breath of fresh air in this respect. It's rather like going back to programming in machine code - and understanding what the bits in the control words are doing. The state machines have a huge 32 byte (shared) memory space for their programs! Mick Zilog Inside! nascom.info for Nascom & Gemini Preliminary MMBasic docs & my PCB designs |
||||
phil99 Guru Joined: 11/02/2018 Location: AustraliaPosts: 1773 |
A small point but global variables don't need to be passed to SUBs at all. Just use them within the body of the sub. They are called global for a reason! |
||||
Grogster Admin Group Joined: 31/12/2012 Location: New ZealandPosts: 9056 |
What was confusing me the most, was the thought that I HAD to define a variable to use for the arguments BEFORE I called the sub - hence my defining the global RX, thinking I needed to have that in place, so it could be used to pass the value to the sub. That thinking was wrong, but that was how I was interpreting things up till last night. As mentioned, borrowed somewhat from the whole ERRORS(D$) concept, but only understanding NOW, that integer variables are a different ONLY cos I was not using the % sign. Had I done that, there would be no problem and I would not have posted the thread. Essentially, I did not even realise that ERRORS(D$) was actually defining the D-string as part of the process, I thought I was using the global D$ to pass the text to the string, when in efect, I guess the sub was defining a totally seperate 2nd D$ for itself during the call, then it vanished when the sub exited, and the global D$ was not touched at all. LOCAL variables I understand to ONLY be defined and ONLY exist inside the sub, and once the sub exits, they vanish - I get that, but I thought you had to have defined GLOBALS to use as a wat to pass the data to the sub via the arguments. That was where I was being tripped up, and had it totally wrong. I now understand that the list of arguments is essentially defined for the sub, every time you call the sub, and don't need to be globals at all. "They're just placeholders" as Tinnie said, and he's quite right once I understand fully what I was doing wrong and how it is REALLY supposed to work! Now that I understand that, I don't think that will trip me up again - famous last words! Fascinating thread, and I have learned something from all of this. Smoke makes things work. When the smoke gets out, it stops! |
||||
Page 1 of 2 |
Print this page |