Home
JAQForum Ver 20.06
Log In or Join  
Active Topics
Local Time 21:27 20 Apr 2024 Privacy Policy
Jump to

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 Zealand
Posts: 9056
Posted: 09:47am 15 Dec 2022
Copy link to clipboard 
Print this post

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 Kingdom
Posts: 3833
Posted: 10:04am 15 Dec 2022
Copy link to clipboard 
Print this post

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 Kingdom
Posts: 3649
Posted: 10:12am 15 Dec 2022
Copy link to clipboard 
Print this post

+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 Zealand
Posts: 9056
Posted: 10:14am 15 Dec 2022
Copy link to clipboard 
Print this post

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 Zealand
Posts: 9056
Posted: 10:22am 15 Dec 2022
Copy link to clipboard 
Print this post

  JohnS said  +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


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 Kingdom
Posts: 3833
Posted: 10:35am 15 Dec 2022
Copy link to clipboard 
Print this post

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


  Quote  SUB ERRORS(D$)
       Print "An error occurred: "+D$
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.

  Quote  ... and is working again just fine once I disabled the OPTION DEFAULT NONE line.


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 Zealand
Posts: 9056
Posted: 10:46am 15 Dec 2022
Copy link to clipboard 
Print this post

Excellent - thank you Tom.  

  thwill said  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.


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 Kingdom
Posts: 3833
Posted: 10:50am 15 Dec 2022
Copy link to clipboard 
Print this post

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 Zealand
Posts: 9056
Posted: 11:01am 15 Dec 2022
Copy link to clipboard 
Print this post

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 Kingdom
Posts: 1646
Posted: 11:32am 15 Dec 2022
Copy link to clipboard 
Print this post

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 Kingdom
Posts: 5707
Posted: 12:27pm 15 Dec 2022
Copy link to clipboard 
Print this post

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 Kingdom
Posts: 3649
Posted: 01:48pm 15 Dec 2022
Copy link to clipboard 
Print this post

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 Kingdom
Posts: 1985
Posted: 01:56pm 15 Dec 2022
Copy link to clipboard 
Print this post

  Grogster said  
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!


... 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 Kingdom
Posts: 409
Posted: 02:34pm 15 Dec 2022
Copy link to clipboard 
Print this post

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 Kingdom
Posts: 3833
Posted: 02:40pm 15 Dec 2022
Copy link to clipboard 
Print this post

  CaptainBoing said  (it matters in counting loops where you might get rapidly into the thousands)


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 Kingdom
Posts: 1985
Posted: 03:02pm 15 Dec 2022
Copy link to clipboard 
Print this post

  thwill said  
Note that I believe this matters considerably less in CMM2, MMB4W and PicoMite


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 Kingdom
Posts: 1646
Posted: 06:10pm 15 Dec 2022
Copy link to clipboard 
Print this post

  CaptainBoing said  

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.
"


No, you are not. I couldn't agree more  

Craig
 
Mixtel90

Guru

Joined: 05/10/2019
Location: United Kingdom
Posts: 5707
Posted: 06:59pm 15 Dec 2022
Copy link to clipboard 
Print this post

I pointed out as much on my Nascom website quite some time ago!
  Quote  Today’s computer user doesn’t have the choice that we had in the past. None of the current computers can be easily programmed in their native machine code. Early home computers all had relatively simple machine code access and didn’t have to worry about segmented memory or different processor modes. This made low level programming very accessible and many users preferred it to the high level languages.

The rot sets in with the introduction of macro assemblers and gets worse through BASIC, Pascal, C, Visual Anything or whatever your favourite programming poison is. The end result is that the true workings of computers become as hidden as the workings of a TV set. This is a pity, as low level programming is not really a difficult task, it just appears that way.

Eventually even the most advanced home computer user only learns high level programming because that is all that is necessary to write spreadsheet or word processor macros.

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: Australia
Posts: 1773
Posted: 09:51pm 15 Dec 2022
Copy link to clipboard 
Print this post

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 Zealand
Posts: 9056
Posted: 10:58pm 15 Dec 2022
Copy link to clipboard 
Print this post

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
© JAQ Software 2024