易码技术论坛

 找回密码
 加入易码
搜索
查看: 146429|回复: 3

[原创]LAVA语言教程

[复制链接]
发表于 2005-1-9 18:30:00 | 显示全部楼层
好像是摘自Lava帮助啊?
发表于 2005-1-9 23:48:00 | 显示全部楼层
原创????????????????????????????????????????????????????????????????????????????????????????????????????????
发表于 2005-1-13 21:39:00 | 显示全部楼层
不过敢把帮助里的东西标榜为“原创”,楼主确实是开天辟地第一人。
楼主莫非就是传说中的“帮助撰写者”?!
 楼主| 发表于 2005-1-9 18:09:31 | 显示全部楼层 |阅读模式
一.什么是LAVA语言  
LAVA就是Lee(开发者的笔名)和JAVA的简称.
LAVA是一种伪编译的语言(这一点与JAVA相同,除此之外在语法上没有任何关系).
LAVA的语法极其类似c(但还是有一些不同).
LAVA程序在电脑端伪编译后,生成由一系列伪指令(伪指令长度一般为1~5字节)组成的lav文件.
lav文件通过文曲星端的LAVA解释器执行.

优点:
1.跨平台
由源代码编译的lav文件不做任何修改即可直接在任何有LAVA解释器的文曲星上执行,无须再次编译.
这一点c做不到,gvbasic也做不到(由于大量gvbasic使用了peek,poke,call等机器相关的语句,造成各机型的basic程序都有不同程度的不兼容).
好处:由于文曲星机型众多,程序员没有时间为每一种机型编写软件,大量软件由用户自己编写.而用户编写的程序一般只适用其拥有的机型,越是新机型,软件越短缺,这也是网上用户抱怨较多的一种原因.而LAVA是跨平台的,新机型可直接使用老机型的lav软件,解决了软件短枪问题.
2.与其他语言的比较
速度:比gvbasic快多了。当然要比c慢,比汇编更慢。但是更快的速度已经不是必要,LAVA有其他特性来弥补这一点。
目标代码的大小:完成同样的任务,目标代码比gvbasic大一些,但要比汇编小,比c小许多。
支持的最大目标文件长度:16M。basic是64K以下,c有32k的限制(超过32k函数调用很麻烦)。
内部函数:basic的函数极其简陋,汇编需要自己写函数,c的函数较丰富,但仍有不足。LAVA的函数库将十分丰富,尤其具有强大高效的绘图函数。lava的绘图函数库,相当于windows的directx。
结构化:basic和汇编都不是结构化语言,c和lava是结构化语言。结构化编程能够减少错误出现的概率。
编程效率:汇编效率很低,basic,c,lava由于是高级语言,效率较高。
用户友好:汇编,c,basic都要求用户对硬件有一定程度的了解。lava通过解释器屏蔽了硬件相关性,用户不需要知道硬件底层(这些工作交给解释器就行了)。


二. LAVA语言语法

(一).lava的数据类型

基本类型:
char:单字节,范围0~255
int:双字节,范围-32768~32767
long:四字节,范围-2147483648~2147483647

构造类型:
数组:包括char数组,int数组,long数组

常量:
整型常量:例如 -1,100,0x4000,'a'
字符串常量:例如 "Lava"

变量名命名规则同c.
变量名最大允许30个字符,超过此长度仍然有效,但超出部分被截去.

lava不支持的c类型:
浮点型
枚举类型
结构体类型
共用体类型
指针类型

本教程不打算写成一个详尽的入门教程.
读者最好有c语言基础.
本节课可参考<C程序设计>第二章相关内容.

(二)运算符和优先级
1. () 圆括号
[] 下标运算符
2. ! 逻辑非运算符
~ 按位取反运算符
++ 自增运算符
-- 自减运算符
- 负号运算符
* 地址运算符(不同于c,后面有详细介绍)
3. * 乘法运算符
/ 除法运算符
% 求余运算符
4. + 加法运算符
- 减法运算符
5. << 左移运算符
>> 右移运算符
6. == != >= <= > < 关系运算符
7. & 按位与运算符
| 按位或运算符
^ 按位异或运算符
8. && 逻辑与运算符
|| 逻辑或运算符
9. = 赋值运算符

所有2级运算符都是单目运算符.其余都是双目运算符.
除2级运算符外,所有运算的结合方向都是自左至右.
不在上面列表的c运算符都不被lava支持.
注意:不支持a=b=c这样的赋值形式.

下面详细讲地址运算符*.
*如果出现在=号(赋值运算符)右边,表示取指定地址的一个字节数据.
例如: a=*8192 表示取内存地址2000处的一个字节数据赋给变量a.
对应的basic语句是:a=peek(8192);
*如果出现在=号(赋值运算符)左边,表示把=号右边的值存到指定地址.
例如: *8192=a 表示把变量a的值存到内存地址8192.
对应的basic语句是:poke 8192,a
地址运算符*的引入,赋予lava语言强大的硬件控制能力.但也带来一些问题.
由于wqx各机型的系统变量定义的地址各有不同,所以滥用*会造成lava无法跨平台执行.
请大家遵守以下约定:
尽量减少地址运算*.
使用地址运算*时请只对lava程序的变量区使用,不要用*对系统变量区读写.
必须用*对系统变量区读写时,在把该程序提交发表时请声明该程序是专门为某某机型写的,无法跨平台运行.
为了便于lava跨平台运行,lava提供了一些符号常量,使用该常量对系统区读写并不影响lava的跨平台运行.
_TEXT: 屏幕文本的缓冲区地址
_GRAPH: 屏幕图形的缓冲区地址
当必须对系统变量区读写时请尽量使用以上符号常量.

与*相关的一些知识:
数组名表示数组的存储起始地址.例如:
char a[10];
int b;
b=a;
*b=5;
*(b+1)=6;

b=a是把数组a的存储起始地址赋给变量b.
*b=5 执行结果相当于a[0]=5;
*(b+1)=6 执行结果相当于a[1]=6;
注意:由于wqx的地址为双字节地址,所以一个变量中要装入一个地址,则该变量至少需要是int.

(三) lava语句
1.控制语句
if () ~else~
for () ~
whiel () ~
do ~ while ()
continue
break
goto
return
上面8种语句中的括号()表示其中是一个条件,~表示内嵌的语句.
注意:lava不支持switch语句,可以用if语句代替.
2.函数调用语句.例如:
printf("This is lava.");
3.表达式语句.例如:
a=3;
i++;
4.空语句.下面是一个空语句:
;
5.可以用{}把一些语句括起来成为复合语句.

本节课可参考<C程序设计>第三,四,五,六章相关内容.

(四) 函数,编译预处理
下面仅指出lava函数与c函数的不同之处.相同之处请参考<C程序设计>第七章内容.
被调用函数必须定义在主调函数之前(目前的编译器暂不支持函数说明).
函数定义必须有类型标识符.下面语句是错误的:
main() {语句}
应该写成:
void main() {语句}
有返回值的函数返回值统一为long型.例如:
int add(int x,int y)
{
return x+y;
}
尽管定义的返回值是int,但仍返回long值.如一定要返回int,请自行转换,如:return (x+y)&0xffff;

编译预处理只支持下面格式:
#define 标识符 整型常量
例如:
#define DELAY_TIME 200
所有编译预处理必须出现在lava语句之前.
系统已经定义好了以下常量:
#define NULL 0
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
#define EOF -1
这些常量不需要在lava程序中定义了.

附录(一):文本模式下的字符显示函数
void putchar(char c) 字符c输出到屏幕
void printf(addr format,args,...) 字符串输出到屏幕
void SetScreen(char mode) mode=0:大字体,mode=1:小字体。设置字体模式
void UpdateLcd(char mode) mode的每一个bit,从高到低控制屏幕的每一行,0表示该行更新,1表示该行不更新。
void Locate(int y,int x) 把字符显示的光标定位在y行x列(x,y均从0开始计算).
常量_TEXT表示屏幕文本缓冲区的地址。采用此常量是为了屏蔽各机种屏幕文本缓冲区的地址的差异(尽管目前各机种屏幕文本缓冲区的地址都相同,但不表示将来也相同)。

putchar,printf会直接更新到屏幕,并不需要UpdateLcd(这一点与winide不同)。
那么什么时候要用到UpdateLcd呢?
看下面例子:
SetScreen(1);
strcpy(_TEXT+52,"I am Lee.");
UpdateLcd(0);
在屏幕的第三行显示出小字体的I am Lee.
学过c的人可能要问,strcpy的第一个参数应该是char *类型啊?
是的,那是c的规定。
在lava,只有char,int,long三种数据基本类型。没有指针的概念。所以,任何数值都可以传递给函数,至于要解释成数值还是地址,由函数的执行体自己决定。
前面printf(addr format,args,...) 出现的addr并不是一种新的数据类型,只是表示该数值会被printf函数当作内存地址处理。
下面出现的addr均表示内存地址.

附录(二):字符函数和字符串函数
int isalnum(char ch)
int isalpha(char ch)
int iscntrl(char ch)
int isdigit(char ch)
int isgraph(char ch)
int islower(char ch)
int isprint(char ch)
int ispunct(char ch)
int isspace(char ch)
int isupper(char ch)
int isxdigit(char ch)
void strcat(addr str1,addr str2)
addr strchr(addr str,char ch)
int strcmp(addr str1,addr str2)
void strcpy(addr str1,addr str2)
int strlen(addr str)
addr strstr(addr str1,addr str2)
char tolower(char ch)
char toupper(char ch)

附录(三):图形模式下的显示函数
void Point(int x,int y,int type) 画点.type=0:清点 type=1:画点
int GetPoint(int x,int y) 取x,y处点的状态.返回值 0:无点,非0:有点
void Line(int x0,int y0,int x1,int y1,int type) 画直线. type=0:清线 type=1:画线
void Box(int x0,int y0,int x1,int y1,int fill,int type) 画矩形 fill=1:填充,fill=0:不填充
type=0:清矩形 type=1:画矩形
void Circle(int x,int y,int r,int fill,int type) 画圆 fill=1:填充,fill=0:不填充
type=0:清圆 type=1:画圆
void Ellipse(int x,int y,int a,int b,int fill,int type) 画椭圆 fill=1:填充,fill=0:不填充
type=0:清椭圆 type=1:画椭圆

附录(四):缓冲区绘图函数
void WriteBlock(int x,int y,int width,int height,int type,addr data)
在屏幕的(x,y)坐标处绘图,图的宽为width,高为height,图形的数据地址为data.
type=1:print
type=2:反相显示
type=3:或
type=4:与
void Block(int x0,int y0,int x1,int y1,int type) type=0:清实心矩形 type=1:画实心矩形
void Rectangle(int x0,int y0,int x1,int y1,int type) type=0:清空心矩形 type=1:画空心矩形(注意:
只画矩形外框,对矩形内部图象无影响)
void TextOut(int x,int y,addr string,int type)
在屏幕的(x,y)坐标处画字符串.
type=1:print
type=2:反相显示
type=3:或
type=4:与
注意:以上函数只在缓冲区内绘图,并不显示在屏幕上.
void Refresh() 把缓冲区内的图象刷新到屏幕上显示.
通过使用缓冲区绘图,可以实现无闪烁绘图.

附录(五):输入函数
char getchar() 等待用户输入一个字符
char Inkey() 读取用户输入,不等待,如无键盘输入,返回0

附录(六):文件操作函数
char fopen(addr filename,addr mode)
void fclose(char fp)
int fread(addr pt,int size,int n,char fp)
int fwrite(addr pt,int size,int n,char fp)
int putc(char ch,char fp)
int getc(char fp)
int fseek(char fp,long offset,char base)
long ftell(char fp)
int feof(char fp)
void rewind(char fp)
以上函数可以对wqx任意目录下的文件进行读写。
注意:fread和fwrite的参数size会被忽略,实际读写的字节数是参数n.之所以保留size是为了与c兼容.

附录(七):其他函数
void Delay(int ms) 延时ms个毫秒,ms最大取值32767(即:32.7秒).
void exit(int exitcode) 退出lava程序.exitcode为退出码
long abs(long x) 取x的绝对值
long rand() 返回一个32位的随机数
void srand(long x) 用x初始化随机数发生器
void Beep() 发出"滴"的声音
void memset(addr data,char val,int size) 把内存地址data开始的size个字节改写为val
void memcpy(addr data1,addr data2,int size) 把内存地址data2开始的size个字节复制到内存地址data1处
void sprintf(addr str,addr format,args,...) 把一个格式字符串输出到str字符串.

与c用法相同的函数不作解释。



   
  
您需要登录后才可以回帖 登录 | 加入易码

本版积分规则

Archiver|手机版|小黑屋|EMAX Studio

GMT+8, 2024-5-5 07:45 , Processed in 0.012235 second(s), 19 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表