This commit is contained in:
Martin Haye 2014-07-06 07:41:01 -07:00
commit 8f8cdb075c
20 changed files with 417 additions and 272 deletions

View File

@ -269,6 +269,28 @@ def strlen(strptr)
return ^strptr
end
```
Pointers to structures or arrays can be referenced with the `->` and `=>` operators, pointing to `byte` or `word` sized elements.
```
const elem_id = 0
const elem_addr = 1
def addentry(entry, id, addr)
entry->elem_id = id ; set ID byte
entry=>elem_addr = addr ; set address
return entry + 3 ; return next enry address
end
```
The above is equivalent to:
```
const elem_id = 0
const elem_addr = 1
def addentry(entry, id, addr)
(entry).elem_id = id ; set ID byte
(entry):elem_addr = addr ; set address
return entry + 3 ; return next enry address
end
```
##### Addresses of Data/Code
Along with dereferencing a pointer, there is the question of getting the address of a variable. The `@` operator prepended to a variable name or a function definition name, will return the address of the variable/definition. From the previous example, the call to `strlen` would look like:
@ -403,13 +425,16 @@ The complex test case is handled with `when`. Basically a `if`, `elsifF`, `else`
when key
is 'A'
; handle A character
break
is 'B'
; handle B character
break
```
...
```
is 'Z'
; handle Z character
break
otherwise
; Not a known key
wend
@ -424,12 +449,15 @@ byte a
when TRUE
is (a <= 10)
; 10 or less
break
is (a > 10) AND (a < 20)
; between 10 and 20
break
is (a >= 20)
; 20 or greater
wend
```
A `when` clause can fall-through to the following clause, just like C `switch` statements by leaving out the `break` at the end of a clause.
##### FOR \<TO,DOWNTO\> [STEP]/NEXT
Iteration over a range is handled with the `for`/`next` loop. When iterating from a smaller to larger value, the `to` construct is used; when iterating from larger to smaller, the `downto` construct is used.

View File

@ -29,6 +29,7 @@ import org.badvision.outlaweditor.data.TileUtils;
import org.badvision.outlaweditor.data.xml.Map;
import org.badvision.outlaweditor.data.xml.Script;
import org.badvision.outlaweditor.data.xml.Tile;
import org.badvision.outlaweditor.ui.ToolType;
/**
*
@ -118,11 +119,17 @@ public class MapEditor extends Editor<Map, MapEditor.DrawMode> implements EventH
public void assignScript(Script script, double x, double y) {
int xx = (int) (x / tileWidth);
int yy = (int) (y / tileHeight);
System.out.println("Dropped " + script.getName() + " at " + xx + "," + yy);
getCurrentMap().putLocationScript(xx, yy, script);
redraw();
}
public void unassignScripts(double x, double y) {
int xx = (int) (x / tileWidth);
int yy = (int) (y / tileHeight);
getCurrentMap().removeLocationScripts(xx, yy);
redraw();
}
public void togglePanZoom() {
anchorPane.getChildren().stream().filter((n) -> !(n == drawCanvas)).forEach((n) -> {
n.setVisible(!n.isVisible());
@ -238,8 +245,8 @@ public class MapEditor extends Editor<Map, MapEditor.DrawMode> implements EventH
}
}
private static final int dashLength=3;
private static final int dashLength = 3;
private void highlightScripts(int x, int y, List<Script> scripts) {
if (scripts == null || scripts.isEmpty()) {
return;
@ -249,41 +256,41 @@ public class MapEditor extends Editor<Map, MapEditor.DrawMode> implements EventH
double xx = x * tileWidth;
double yy = y * tileHeight;
gc.setLineWidth(4);
for (int i = 0; i < tileWidth-2; i += dashLength) {
for (int i = 0; i < tileWidth - 2; i += dashLength) {
idx = (idx + 1) % scripts.size();
gc.beginPath();
gc.moveTo(xx,yy);
gc.setStroke(currentMap.getScriptColor(scripts.get(idx)));
gc.moveTo(xx, yy);
currentMap.getScriptColor(scripts.get(idx)).ifPresent(gc::setStroke);
xx += dashLength;
gc.lineTo(xx, yy);
gc.setEffect(new DropShadow(2, Color.BLACK));
gc.stroke();
}
for (int i = 0; i < tileHeight-2; i += dashLength) {
for (int i = 0; i < tileHeight - 2; i += dashLength) {
idx = (idx + 1) % scripts.size();
gc.beginPath();
gc.moveTo(xx,yy);
gc.setStroke(currentMap.getScriptColor(scripts.get(idx)));
gc.moveTo(xx, yy);
currentMap.getScriptColor(scripts.get(idx)).ifPresent(gc::setStroke);
yy += dashLength;
gc.lineTo(xx, yy);
gc.setEffect(new DropShadow(2, Color.BLACK));
gc.stroke();
}
for (int i = 0; i < tileWidth-2; i += dashLength) {
for (int i = 0; i < tileWidth - 2; i += dashLength) {
idx = (idx + 1) % scripts.size();
gc.beginPath();
gc.moveTo(xx,yy);
gc.setStroke(currentMap.getScriptColor(scripts.get(idx)));
gc.moveTo(xx, yy);
currentMap.getScriptColor(scripts.get(idx)).ifPresent(gc::setStroke);
xx -= dashLength;
gc.lineTo(xx, yy);
gc.setEffect(new DropShadow(2, Color.BLACK));
gc.stroke();
}
for (int i = 0; i < tileHeight-2; i += dashLength) {
for (int i = 0; i < tileHeight - 2; i += dashLength) {
idx = (idx + 1) % scripts.size();
gc.beginPath();
gc.moveTo(xx,yy);
gc.setStroke(currentMap.getScriptColor(scripts.get(idx)));
gc.moveTo(xx, yy);
currentMap.getScriptColor(scripts.get(idx)).ifPresent(gc::setStroke);
yy -= dashLength;
gc.lineTo(xx, yy);
gc.setEffect(new DropShadow(2, Color.BLACK));
@ -291,10 +298,13 @@ public class MapEditor extends Editor<Map, MapEditor.DrawMode> implements EventH
}
}
public void setupDragDrop(TransferHelper<Script> scriptHelper) {
public void setupDragDrop(TransferHelper<Script> scriptHelper, TransferHelper<ToolType> toolHelper) {
scriptHelper.registerDropSupport(drawCanvas, (Script script, double x, double y) -> {
assignScript(script, x, y);
});
toolHelper.registerDropSupport(drawCanvas, (ToolType tool, double x, double y) -> {
unassignScripts(x, y);
});
}

View File

@ -3,7 +3,7 @@ package org.badvision.outlaweditor;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import javafx.event.EventHandler;
import javafx.scene.ImageCursor;
import javafx.scene.Node;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.DataFormat;
@ -11,6 +11,7 @@ import javafx.scene.input.DragEvent;
import javafx.scene.input.Dragboard;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.TransferMode;
import org.badvision.outlaweditor.ui.ToolType;
/**
* Simplify management of drag/drop operations
@ -27,6 +28,7 @@ public class TransferHelper<T> {
static Map<String, DataFormat> dataFormats = new HashMap<>();
public interface DropEventHandler<T> {
public void handle(T object, double x, double y);
}
@ -50,35 +52,50 @@ public class TransferHelper<T> {
source.setOnDragDetected((MouseEvent event) -> {
registry.put(id, object);
Dragboard db = source.startDragAndDrop(TransferMode.LINK);
if (type.isAssignableFrom(ToolType.class)) {
ToolType tool = (ToolType) object;
tool.getIcon().ifPresent(db::setDragView);
}
ClipboardContent content = new ClipboardContent();
content.put(format, id);
db.setContent(content);
event.consume();
dropSupportRegisterHandler.run();
});
source.setOnDragDone((DragEvent event) -> {
registry.remove(id);
dropSupportRegisterHandler.run();
});
}
Runnable dropSupportRegisterHandler;
Runnable dropSupportUnregisterHandler;
public void registerDropSupport(final Node target, final DropEventHandler<T> handler) {
target.setOnDragOver((DragEvent event) -> {
Dragboard db = event.getDragboard();
if (db.getContentTypes().contains(format)) {
event.acceptTransferModes(TransferMode.LINK);
}
event.consume();
});
target.setOnDragDropped((DragEvent event) -> {
Dragboard db = event.getDragboard();
if (db.getContentTypes().contains(format)) {
event.setDropCompleted(true);
String id = (String) db.getContent(format);
T object = (T) registry.get(id);
handler.handle(object, event.getX(), event.getY());
} else {
event.setDropCompleted(false);
}
event.consume();
});
dropSupportUnregisterHandler = () -> {
target.setOnDragOver(null);
target.setOnDragDropped(null);
};
dropSupportRegisterHandler = () -> {
target.setOnDragOver((DragEvent event) -> {
Dragboard db = event.getDragboard();
if (db.getContentTypes().contains(format)) {
event.acceptTransferModes(TransferMode.LINK);
}
event.consume();
});
target.setOnDragDropped((DragEvent event) -> {
Dragboard db = event.getDragboard();
if (db.getContentTypes().contains(format)) {
event.setDropCompleted(true);
String id = (String) db.getContent(format);
T object = (T) registry.get(id);
handler.handle(object, event.getX(), event.getY());
} else {
event.setDropCompleted(false);
}
event.consume();
});
};
}
}

View File

@ -6,6 +6,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import javafx.scene.image.WritableImage;
import javafx.scene.paint.Color;
@ -45,11 +46,11 @@ public class TileMap extends ArrayList<ArrayList<Tile>> implements Serializable
public static double HUE = 180;
private final java.util.Map<Integer, List<Script>> locationScripts = new HashMap<>();
private final java.util.Map<Script, Color> scriptColors = new HashMap<>();
public Color getScriptColor(Script s) {
return scriptColors.get(s);
public Optional<Color> getScriptColor(Script s) {
return Optional.ofNullable(scriptColors.get(s));
}
public List<Script> getLocationScripts(int x, int y) {
List<Script> list = locationScripts.get(getMortonNumber(x, y));
if (list != null) {
@ -67,6 +68,20 @@ public class TileMap extends ArrayList<ArrayList<Tile>> implements Serializable
registerLocationScript(x, y, s);
}
public void removeLocationScripts(int x, int y) {
int loc = getMortonNumber(x, y);
List<Script> scripts = locationScripts.get(loc);
if (scripts != null) {
scripts.forEach(s -> {
s.getLocationTrigger().removeIf(t -> {
return t.getX() == x && t.getY() == y;
});
});
}
locationScripts.remove(loc);
Application.getInstance().getController().redrawScripts();
}
private void registerLocationScript(int x, int y, Script s) {
if (!scriptColors.containsKey(s)) {
scriptColors.put(s, Color.hsb(HUE, SATURATION, VALUE));
@ -79,6 +94,7 @@ public class TileMap extends ArrayList<ArrayList<Tile>> implements Serializable
locationScripts.put(loc, list);
}
list.add(s);
Application.getInstance().getController().redrawScripts();
}
private int getMortonNumber(int x, int y) {
@ -157,7 +173,7 @@ public class TileMap extends ArrayList<ArrayList<Tile>> implements Serializable
)
);
}
m.getChunk().forEach( c-> {
m.getChunk().forEach(c -> {
int y = c.getY();
for (JAXBElement<List<String>> row : c.getRow()) {
int x = c.getX();

View File

@ -2,6 +2,7 @@ package org.badvision.outlaweditor.ui;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ListView;
@ -52,7 +53,9 @@ public abstract class MapEditorTabController {
protected TextField mapWidthField; // Value injected by FXMLLoader
@FXML // fx:id="mapWrapAround"
protected CheckBox mapWrapAround; // Value injected by FXMLLoader
@FXML
protected Button scriptEraseTool;
@FXML
abstract public void mapDraw1(ActionEvent event);

View File

@ -0,0 +1,20 @@
package org.badvision.outlaweditor.ui;
import java.util.Optional;
import javafx.scene.image.Image;
public enum ToolType {
ERASER("images/eraser.png"), FILL(null), SELECT(null), MOVE(null), DRAW(null);
ToolType(String iconPath) {
if (iconPath != null) {
icon = Optional.of(new Image(iconPath));
} else {
icon = Optional.empty();
}
}
Optional<Image> icon;
public Optional<Image> getIcon() {
return icon;
}
}

View File

@ -1,6 +1,5 @@
package org.badvision.outlaweditor.ui.impl;
import org.badvision.outlaweditor.ui.EntitySelectorCell;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.event.ActionEvent;
@ -12,19 +11,21 @@ import javafx.scene.image.ImageView;
import javafx.scene.image.WritableImage;
import javafx.util.Callback;
import org.badvision.outlaweditor.Application;
import org.badvision.outlaweditor.MapEditor;
import org.badvision.outlaweditor.TransferHelper;
import static org.badvision.outlaweditor.Application.currentPlatform;
import static org.badvision.outlaweditor.Application.gameData;
import static org.badvision.outlaweditor.ui.UIAction.confirm;
import static org.badvision.outlaweditor.ui.UIAction.createAndEditScript;
import org.badvision.outlaweditor.MapEditor;
import org.badvision.outlaweditor.TransferHelper;
import static org.badvision.outlaweditor.data.PropertyHelper.bind;
import static org.badvision.outlaweditor.data.PropertyHelper.stringProp;
import org.badvision.outlaweditor.data.TileUtils;
import org.badvision.outlaweditor.data.xml.Script;
import org.badvision.outlaweditor.data.xml.Map;
import org.badvision.outlaweditor.data.xml.Script;
import org.badvision.outlaweditor.ui.EntitySelectorCell;
import org.badvision.outlaweditor.ui.MapEditorTabController;
import org.badvision.outlaweditor.ui.ToolType;
import org.badvision.outlaweditor.ui.UIAction;
import static org.badvision.outlaweditor.ui.UIAction.confirm;
import static org.badvision.outlaweditor.ui.UIAction.createAndEditScript;
/**
*
@ -32,6 +33,7 @@ import org.badvision.outlaweditor.ui.UIAction;
*/
public class MapEditorTabControllerImpl extends MapEditorTabController {
final TransferHelper<Script> scriptDragDrop = new TransferHelper<>(Script.class);
final TransferHelper<ToolType> toolDragDrop = new TransferHelper<>(ToolType.class);
@Override
public void mapDraw1(ActionEvent event) {
@ -234,7 +236,7 @@ public class MapEditorTabControllerImpl extends MapEditorTabController {
e.setEntity(m);
e.buildEditorUI(mapEditorAnchorPane);
setCurrentEditor(e);
e.setupDragDrop(scriptDragDrop);
e.setupDragDrop(scriptDragDrop, toolDragDrop);
}
redrawMapScripts();
}
@ -270,6 +272,7 @@ public class MapEditorTabControllerImpl extends MapEditorTabController {
public void finishUpdate(Map item) {
}
});
toolDragDrop.registerDragSupport(scriptEraseTool, ToolType.ERASER);
}
@Override
@ -306,6 +309,7 @@ public class MapEditorTabControllerImpl extends MapEditorTabController {
if (empty || item == null) {
setText("");
} else {
getCurrentEditor().getCurrentMap().getScriptColor(item).ifPresent(this::setTextFill);
setText(item.getName());
scriptDragDrop.registerDragSupport(this, item);
}

View File

@ -2,7 +2,6 @@
<?import java.lang.*?>
<?import java.net.*?>
<?import javafx.collections.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
@ -10,29 +9,28 @@
<children>
<VBox prefHeight="500.0" prefWidth="800.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<fx:include fx:id="menu" source="Menubar.fxml"/>
<fx:include fx:id="menu" source="Menubar.fxml" />
<TabPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="455.0" prefWidth="676.9998779296875" tabClosingPolicy="UNAVAILABLE" VBox.vgrow="ALWAYS">
<tabs>
<Tab onSelectionChanged="#tileTabActivated" text="Tiles">
<content>
<fx:include fx:id="tile" source="tileEditorTab.fxml"/>
<fx:include fx:id="tile" source="tileEditorTab.fxml" />
</content>
</Tab>
<Tab onSelectionChanged="#mapTabActivated" text="Maps">
<content>
<fx:include fx:id="map" source="mapEditorTab.fxml"/>
<fx:include fx:id="map" source="mapEditorTab.fxml" />
</content>
</Tab>
<Tab onSelectionChanged="#imageTabActivated" text="Images">
<content>
<fx:include fx:id="image" source="imageEditorTab.fxml"/>
<fx:include fx:id="image" source="imageEditorTab.fxml" />
</content>
</Tab>
</tabs>
</TabPane>
</children>
</VBox>
<HBox layoutX="300.0" layoutY="200.0" prefHeight="100.0" prefWidth="200.0" />
</children>
<stylesheets>
<URL value="@styles/applicationui.css" />

View File

@ -1,23 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import org.tbee.javafx.scene.layout.fxml.MigPane?>
<?import layouttests.migfxml.sample1.*?>
<MigPane id="rootPane" fx:controller="org.badvision.outlaweditor.HelloController"
styleClass="main-panel"
layout="insets 20"
cols="[label, pref!][grow, 50::]"
rows=""
xmlns:fx="http://javafx.com/fxml">
<Label text="First Name:" /> <TextField fx:id="firstNameField" prefColumnCount="30" MigPane.cc="growx, wrap" />
<Label text="Last Name:" /> <TextField fx:id="lastNameField" prefColumnCount="30" MigPane.cc="growx, wrap" />
<Button text="Say Hello" onAction="#sayHello" MigPane.cc="skip, gap :push, gaptop 15, wrap" />
<Label fx:id="messageLabel" styleClass="hello-message" MigPane.cc="span, growx, gaptop 15" />
</MigPane >

Binary file not shown.

After

Width:  |  Height:  |  Size: 774 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -59,7 +59,7 @@
<items>
<Button mnemonicParsing="false" onAction="#onMapScriptAddPressed" text="+" />
<Button mnemonicParsing="false" onAction="#onMapScriptDeletePressed" text="-" />
<Button mnemonicParsing="false" onAction="#onMapScriptClonePressed" text="Clone" />
<Button mnemonicParsing="false" onAction="#onMapScriptClonePressed" text="Clone" /><Button fx:id="scriptEraseTool" mnemonicParsing="false" prefHeight="34.0" prefWidth="29.0" styleClass="eraseButton" text="E" />
</items>
</ToolBar><TextArea fx:id="scriptInfo" editable="false" layoutY="340.0" prefHeight="100.0" prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" />
</children>

View File

@ -7,19 +7,25 @@
}
.moveButton {
-fx-graphic: url("../images/arrowUp.png");
-fx-graphic: url("../images/arrowUp.png");
}
.zoomOutButton {
-fx-graphic: url("../images/zoomOut.png");
-fx-graphic: url("../images/zoomOut.png");
}
.zoomInButton {
-fx-graphic: url("../images/zoomIn.png");
-fx-graphic: url("../images/zoomIn.png");
}
.moveButton, .zoomInButton, .zoomOutButton{
-fx-background-color: rgba(0,0,0,0);
-fx-content-display: graphic-only;
-fx-effect: dropshadow(gaussian, navy, 10, 0.5, 0, 0);
-fx-background-color: rgba(0,0,0,0);
-fx-content-display: graphic-only;
-fx-effect: dropshadow(gaussian, navy, 10, 0.5, 0, 0);
}
.eraseButton {
-fx-graphic: url("../images/eraser-icon.png");
-fx-content-display: graphic-only;
-fx-background-color: rgba(0,0,0,0);
}

View File

@ -268,26 +268,33 @@ Control structures affect the flow of control through the program. There are co
fin
```
The when/is/otherwise/wend statement is similar to the if/elsif/else/fin construct except that it is more efficient. It selects one path based on the evaluated expressions, then merges the code path back together at the end. However only the 'when' value is compared against a list of expressions. The expressions do not need to be constants, they can be any valid expression. The list of expressions is evaluated in order, so for efficiency sake, place the most common cases earlier in the list.
The when/is/otherwise/wend statement is similar to the if/elsif/else/fin construct except that it is more efficient. It selects one path based on the evaluated expressions, then merges the code path back together at the end. However only the 'when' value is compared against a list of expressions. The expressions do not need to be constants, they can be any valid expression. The list of expressions is evaluated in order, so for efficiency sake, place the most common cases earlier in the list. Just as in C programs, a 'break' statement is required to keep one clause from falling through to the next. Falling through from one clause to the next can have it's uses, so this behavior has been added to PLASMA.
```
when keypressed
is keyarrowup
cursup
break
is keyarrowdown
cursdown
break
is keyarrowleft
cursleft
break
is keyarrowright
cursright
break
is keyctrlx
cutline
break
is keyctrlv
pasteline
break
is keyescape
cursoff
cmdmode
redraw
break
otherwise
bell
wend

View File

@ -812,8 +812,8 @@ def addsym(sym, addr)
lastsym = lastsym + 1
sym = sym + 1
loop
(lastsym).0 = ^sym
(lastsym):1 = addr
lastsym->0 = ^sym
lastsym=>1 = addr
lastsym = lastsym + 3
^lastsym = 0
end
@ -839,7 +839,7 @@ def lookupextern(esd, index)
while ^esd
sym = esd
esd = esd + dcitos(esd, @str)
if (esd).0 & $10 and (esd).1 == index
if esd->0 & $10 and esd->1 == index
addr = lookupsym(sym)
if !addr
perr = $81
@ -858,18 +858,18 @@ def adddef(bank, addr, deflast)
defentry = *deflast
*deflast = defentry + 5
if bank
(defentry):1 = $03DC ; JSR $03DC (AUX MEM INTERP)
defentry=>1 = $03DC ; JSR $03DC (AUX MEM INTERP)
else
(defentry):1 = $03D6 ; JSR $03D6 (MAIN MEM INTERP)
defentry=>1 = $03D6 ; JSR $03D6 (MAIN MEM INTERP)
fin
(defentry).0 = $20
(defentry):3 = addr
(defentry).5 = 0 ; NULL out next entry
defentry->0 = $20
defentry=>3 = addr
defentry->5 = 0 ; NULL out next entry
return defentry
end
def lookupdef(addr, deftbl)
while (deftbl).0 == $20
if (deftbl):3 == addr
while deftbl->0 == $20
if deftbl=>3 == addr
return deftbl
fin
deftbl = deftbl + 5
@ -983,9 +983,9 @@ def loadmod(mod)
;
; This is a bytcode def entry - add it to the def directory.
;
adddef(defbank, (rld):1 - defofst + defaddr, @deflast)
adddef(defbank, rld=>1 - defofst + defaddr, @deflast)
else
addr = (rld):1 + modfix
addr = rld=>1 + modfix
if uword_isge(addr, modaddr) ; Skip fixups to header
if ^rld & $80 ; WORD sized fixup.
fixup = *addr
@ -993,7 +993,7 @@ def loadmod(mod)
fixup = ^addr
fin
if ^rld & $10 ; EXTERN reference.
fixup = fixup + lookupextern(esd, (rld).3)
fixup = fixup + lookupextern(esd, rld->3)
else ; INTERN fixup.
fixup = fixup + modfix - MODADDR
if uword_isge(fixup, bytecode)
@ -1022,7 +1022,7 @@ def loadmod(mod)
;
; EXPORT symbol - add it to the global symbol table.
;
addr = (esd):1 + modfix - MODADDR
addr = esd=>1 + modfix - MODADDR
if uword_isge(addr, bytecode)
;
; Use the def directory address for bytecode.
@ -1123,10 +1123,10 @@ def catalog(optpath)
if type & $F0 == $D0 ; Is it a directory?
cout('/')
len = len + 1
elsif (entry).$10 == $FF
elsif entry->$10 == $FF
cout('-')
len = len + 1
elsif (entry).$10 == $FE
elsif entry->$10 == $FE
cout('+')
len = len + 1
fin
@ -1250,8 +1250,8 @@ heap = *freemem
stodci(@stdlibstr, heap)
addmod(heap, @version)
while *stdlibsym
stodci((stdlibsym):0, heap)
addsym(heap, (stdlibsym):2)
stodci(stdlibsym=>0, heap)
addsym(heap, stdlibsym=>2)
stdlibsym = stdlibsym + 4
loop
;

View File

@ -22,28 +22,28 @@ t_token keywords[] = {
ENDCASE_TOKEN, 'W', 'E', 'N', 'D',
FOR_TOKEN, 'F', 'O', 'R',
TO_TOKEN, 'T', 'O',
DOWNTO_TOKEN, 'D', 'O', 'W', 'N', 'T', 'O',
DOWNTO_TOKEN, 'D', 'O', 'W', 'N', 'T', 'O',
STEP_TOKEN, 'S', 'T', 'E', 'P',
NEXT_TOKEN, 'N', 'E', 'X', 'T',
REPEAT_TOKEN, 'R', 'E', 'P', 'E', 'A', 'T',
UNTIL_TOKEN, 'U', 'N', 'T', 'I', 'L',
BREAK_TOKEN, 'B', 'R', 'E', 'A', 'K',
UNTIL_TOKEN, 'U', 'N', 'T', 'I', 'L',
BREAK_TOKEN, 'B', 'R', 'E', 'A', 'K',
ASM_TOKEN, 'A', 'S', 'M',
DEF_TOKEN, 'D', 'E', 'F',
EXPORT_TOKEN, 'E', 'X', 'P', 'O', 'R', 'T',
IMPORT_TOKEN, 'I', 'M', 'P', 'O', 'R', 'T',
EXPORT_TOKEN, 'E', 'X', 'P', 'O', 'R', 'T',
IMPORT_TOKEN, 'I', 'M', 'P', 'O', 'R', 'T',
RETURN_TOKEN, 'R', 'E', 'T', 'U', 'R', 'N',
END_TOKEN, 'E', 'N', 'D',
EXIT_TOKEN, 'E', 'X', 'I', 'T',
DONE_TOKEN, 'D', 'O', 'N', 'E',
LOGIC_NOT_TOKEN, 'N', 'O', 'T',
LOGIC_AND_TOKEN, 'A', 'N', 'D',
LOGIC_OR_TOKEN, 'O', 'R',
LOGIC_OR_TOKEN, 'O', 'R',
BYTE_TOKEN, 'B', 'Y', 'T', 'E',
WORD_TOKEN, 'W', 'O', 'R', 'D',
CONST_TOKEN, 'C', 'O', 'N', 'S', 'T',
PREDEF_TOKEN, 'P', 'R', 'E', 'D', 'E', 'F',
SYSFLAGS_TOKEN, 'S', 'Y', 'S', 'F', 'L', 'A', 'G', 'S',
SYSFLAGS_TOKEN, 'S', 'Y', 'S', 'F', 'L', 'A', 'G', 'S',
EOL_TOKEN
};
@ -293,6 +293,11 @@ t_token scan(void)
scantoken = EQ_TOKEN;
scanpos += 2;
}
else if (scanpos[1] == '>')
{
scantoken = PTRW_TOKEN;
scanpos += 2;
}
else
{
scantoken = SET_TOKEN;
@ -317,6 +322,11 @@ t_token scan(void)
scantoken = DEC_TOKEN;
scanpos += 2;
}
else if (scanpos[1] == '>')
{
scantoken = PTRB_TOKEN;
scanpos += 2;
}
else
{
scantoken = SUB_TOKEN;

View File

@ -288,108 +288,25 @@ int parse_value(int rvalue)
*/
while (scan() == OPEN_PAREN_TOKEN
|| scantoken == OPEN_BRACKET_TOKEN
|| scantoken == PTRB_TOKEN
|| scantoken == PTRW_TOKEN
|| scantoken == DOT_TOKEN
|| scantoken == COLON_TOKEN)
{
if (scantoken == OPEN_BRACKET_TOKEN)
switch (scantoken)
{
/*
* Array
*/
if (!emit_value)
{
if (type & ADDR_TYPE)
{
if (type & LOCAL_TYPE)
emit_localaddr(value);
else
emit_globaladdr(value, 0, type);
}
else if (type & CONST_TYPE)
{
emit_const(value);
}
emit_value = 1;
}
if (type & PTR_TYPE)
emit_lw();
if (!parse_expr())
{
parse_error("Bad expression");
return (0);
}
if (scantoken != CLOSE_BRACKET_TOKEN)
{
parse_error("Missing closing bracket");
return (0);
}
if (type & WORD_TYPE)
{
//type |= WPTR_TYPE;
type = WPTR_TYPE;
emit_indexword();
}
else
{
//type |= BPTR_TYPE;
type = BPTR_TYPE;
emit_indexbyte();
}
//type &= ~(ADDR_TYPE | CONST_TYPE);
}
else if (scantoken == DOT_TOKEN || scantoken == COLON_TOKEN)
{
/*
* Structure member offset or array of arrays
*/
elem_type = (scantoken == DOT_TOKEN) ? BPTR_TYPE : WPTR_TYPE;
if (parse_constval(&elem_offset, &elem_size))
{
case OPEN_BRACKET_TOKEN:
/*
* Constant member offset
*/
if (!emit_value)
{
if (type & VAR_TYPE)
{
elem_type = (type & ~VAR_TYPE) | (elem_type == BPTR_TYPE ? BYTE_TYPE : WORD_TYPE);
}
else if (type & CONST_TYPE)
{
value += elem_offset;
emit_const(value);
elem_offset = 0;
emit_value = 1;
}
else // FUNC_TYPE
{
emit_globaladdr(value, elem_offset, type);
emit_value = 1;
}
}
else
{
if (elem_offset != 0)
{
emit_const(elem_offset);
emit_op(ADD_TOKEN);
elem_offset = 0;
}
}
}
else if (scantoken == OPEN_BRACKET_TOKEN)
{
/*
* Array of arrays
* Array
*/
if (!emit_value)
{
if (type & ADDR_TYPE)
{
if (type & LOCAL_TYPE)
emit_localaddr(value + elem_offset);
emit_localaddr(value);
else
emit_globaladdr(value, elem_offset, type);
emit_globaladdr(value, 0, type);
}
else if (type & CONST_TYPE)
{
@ -397,75 +314,181 @@ int parse_value(int rvalue)
}
emit_value = 1;
}
while (parse_expr())
{
if (scantoken != COMMA_TOKEN)
break;
emit_indexword();
if (type & PTR_TYPE)
emit_lw();
if (!parse_expr())
{
parse_error("Bad expression");
return (0);
}
if (scantoken != CLOSE_BRACKET_TOKEN)
{
parse_error("Missing closing bracket");
return (0);
}
if (elem_type & WPTR_TYPE)
emit_indexword();
else
emit_indexbyte();
}
else
{
parse_error("Invalid member offset");
return (0);
}
type = elem_type; //(type & ~(ADDR_TYPE | CONST_TYPE)) | elem_type;
}
else if (scantoken == OPEN_PAREN_TOKEN)
{
/*
* Function call
*/
if (emit_value && !(type & (FUNC_TYPE | CONST_TYPE)))
{
if (scan_lookahead() != CLOSE_PAREN_TOKEN)
emit_push();
}
cparams = 0;
while (parse_expr())
{
cparams++;
if (scantoken != COMMA_TOKEN)
break;
}
if (scantoken != CLOSE_PAREN_TOKEN)
{
parse_error("Missing closing parenthesis");
return (0);
}
if (type & (FUNC_TYPE | CONST_TYPE))
emit_call(value, type);
else
{
if (!emit_value)
if (type & WORD_TYPE)
{
if (type & VAR_TYPE)
{
if (type & LOCAL_TYPE)
emit_llw(value + elem_offset);
else
emit_law(value, elem_offset, type);
}
else if (type & PTR_TYPE)
emit_lw();
//type |= WPTR_TYPE;
type = WPTR_TYPE;
emit_indexword();
}
else
if (cparams)
emit_pull();
emit_ical();
}
emit_value = 1;
type = WORD_TYPE; //(type & ~(FUNC_TYPE | CONST_TYPE)) | WORD_TYPE;
{
//type |= BPTR_TYPE;
type = BPTR_TYPE;
emit_indexbyte();
}
//type &= ~(ADDR_TYPE | CONST_TYPE);
break;
case PTRB_TOKEN:
case PTRW_TOKEN:
if (!emit_value)
{
if (type & FUNC_TYPE)
emit_call(value, type);
else if (type & VAR_TYPE)
{
if (type & LOCAL_TYPE)
(type & BYTE_TYPE) ? emit_llb(value + elem_offset) : emit_llw(value + elem_offset);
else
(type & BYTE_TYPE) ? emit_lab(value, elem_offset, type) : emit_law(value, elem_offset, type);
}
else
(type & BPTR_TYPE) ? emit_lb() : emit_lw();
}
emit_value = 1;
type &= ~(VAR_TYPE | ADDR_TYPE);
type |= WORD_TYPE;
scantoken = scantoken == PTRB_TOKEN ? DOT_TOKEN : COLON_TOKEN;
case DOT_TOKEN:
case COLON_TOKEN:
/*
* Structure member offset or array of arrays
*/
elem_type = (scantoken == DOT_TOKEN) ? BPTR_TYPE : WPTR_TYPE;
if (parse_constval(&elem_offset, &elem_size))
{
/*
* Constant member offset
*/
if (!emit_value)
{
if (type & VAR_TYPE)
{
elem_type = (type & ~VAR_TYPE) | (elem_type == BPTR_TYPE ? BYTE_TYPE : WORD_TYPE);
}
else if (type & CONST_TYPE)
{
value += elem_offset;
emit_const(value);
elem_offset = 0;
emit_value = 1;
}
else // FUNC_TYPE
{
emit_globaladdr(value, elem_offset, type);
emit_value = 1;
}
}
else
{
if (elem_offset != 0)
{
emit_const(elem_offset);
emit_op(ADD_TOKEN);
elem_offset = 0;
}
}
}
else if (scantoken == OPEN_BRACKET_TOKEN)
{
/*
* Array of arrays
*/
if (!emit_value)
{
if (type & ADDR_TYPE)
{
if (type & LOCAL_TYPE)
emit_localaddr(value + elem_offset);
else
emit_globaladdr(value, elem_offset, type);
}
else if (type & CONST_TYPE)
{
emit_const(value);
}
emit_value = 1;
}
while (parse_expr())
{
if (scantoken != COMMA_TOKEN)
break;
emit_indexword();
emit_lw();
}
if (scantoken != CLOSE_BRACKET_TOKEN)
{
parse_error("Missing closing bracket");
return (0);
}
if (elem_type & WPTR_TYPE)
emit_indexword();
else
emit_indexbyte();
}
else
{
parse_error("Invalid member offset");
return (0);
}
type = elem_type; //(type & ~(ADDR_TYPE | CONST_TYPE)) | elem_type;
break;
case OPEN_PAREN_TOKEN:
/*
* Function call
*/
if (emit_value && !(type & (FUNC_TYPE | CONST_TYPE)))
{
if (scan_lookahead() != CLOSE_PAREN_TOKEN)
emit_push();
}
cparams = 0;
while (parse_expr())
{
cparams++;
if (scantoken != COMMA_TOKEN)
break;
}
if (scantoken != CLOSE_PAREN_TOKEN)
{
parse_error("Missing closing parenthesis");
return (0);
}
if (type & (FUNC_TYPE | CONST_TYPE))
emit_call(value, type);
else
{
if (!emit_value)
{
if (type & VAR_TYPE)
{
if (type & LOCAL_TYPE)
emit_llw(value + elem_offset);
else
emit_law(value, elem_offset, type);
}
else if (type & PTR_TYPE)
emit_lw();
}
else
if (cparams)
emit_pull();
emit_ical();
}
emit_value = 1;
type = WORD_TYPE; //(type & ~(FUNC_TYPE | CONST_TYPE)) | WORD_TYPE;
break;
}
}
if (emit_value)
@ -611,15 +634,15 @@ int parse_expr()
}
int parse_stmnt(void)
{
int tag_prevbrk, tag_else, tag_endif, tag_while, tag_wend, tag_repeat, tag_for, tag_choice, type, addr, step;
int tag_prevbrk, tag_else, tag_endif, tag_while, tag_wend, tag_repeat, tag_for, tag_choice, tag_of;
int type, addr, step;
char *idptr;
/*
* Optimization for last function LEAVE
* Optimization for last function LEAVE and OF clause.
*/
if (scantoken != END_TOKEN && scantoken != DONE_TOKEN)
if (scantoken != END_TOKEN && scantoken != DONE_TOKEN && scantoken != OF_TOKEN && scantoken != DEFAULT_TOKEN)
prevstmnt = scantoken;
switch (scantoken)
{
case IF_TOKEN:
@ -779,6 +802,7 @@ int parse_stmnt(void)
tag_prevbrk = break_tag;
break_tag = tag_new(BRANCH_TYPE);
tag_choice = tag_new(BRANCH_TYPE);
tag_of = tag_new(BRANCH_TYPE);
if (!parse_expr())
{
parse_error("Bad CASE expression");
@ -795,13 +819,18 @@ int parse_stmnt(void)
return (0);
}
emit_brne(tag_choice);
emit_codetag(tag_of);
while (parse_stmnt()) next_line();
emit_brnch(break_tag);
tag_of = tag_new(BRANCH_TYPE);
if (prevstmnt != BREAK_TOKEN) // Fall through to next OF if no break
emit_brnch(tag_of);
emit_codetag(tag_choice);
tag_choice = tag_new(BRANCH_TYPE);
}
else if (scantoken == DEFAULT_TOKEN)
{
emit_codetag(tag_of);
tag_of = 0;
scan();
while (parse_stmnt()) next_line();
if (scantoken != ENDCASE_TOKEN)
@ -816,6 +845,8 @@ int parse_stmnt(void)
return (0);
}
}
if (tag_of)
emit_codetag(tag_of);
emit_codetag(break_tag);
emit_drop();
break_tag = tag_prevbrk;

View File

@ -630,16 +630,16 @@ LNOT1 EOR #$FF
;*
;* LOGICAL AND
;*
LAND LDA ESTKL,X
ORA ESTKH,X
BEQ LAND1
LDA ESTKL+1,X
LAND LDA ESTKL+1,X
ORA ESTKH+1,X
BEQ LAND2
LDA ESTKL,X
ORA ESTKH,X
BEQ LAND1
LDA #$FF
LAND1 STA ESTKL+1,X
STA ESTKH+1,X
INX
LAND2 INX
JMP NEXTOP
;*
;* LOGICAL OR
@ -650,9 +650,9 @@ LOR LDA ESTKL,X
ORA ESTKH+1,X
BEQ LOR1
LDA #$FF
LOR1 STA ESTKL+1,X
STA ESTKL+1,X
STA ESTKH+1,X
INX
LOR1 INX
JMP NEXTOP
;*
;* SWAP TOS WITH TOS-1

View File

@ -17,6 +17,7 @@ byte a2e[] = "//e"
byte a2c[] = "//c"
byte a3[] = "///"
word struct[] = 1, 10, 100, 1000, 10000
word ptr
byte spaces[] = " "
;
@ -61,21 +62,36 @@ export def main(range)
when MACHID & $C8
is $08
puts(@a1)
break
is $00
puts(@a2)
break
is $40
puts(@a2p)
break
is $80
puts(@a2e)
break
is $88
puts(@a2c)
break
is $C0
puts(@a3)
break
otherwise
putc('?')
wend
putln
end
ptr=@struct
main(@struct:6)
puti((ptr):6)
putln
puti(ptr=>6)
putln
puti((ptr).6)
putln
puti(ptr->6)
putln
done

View File

@ -85,6 +85,8 @@
#define DEC_TOKEN TOKEN('K')
#define BPTR_TOKEN TOKEN('^')
#define WPTR_TOKEN TOKEN('*')
#define PTRB_TOKEN TOKEN('b')
#define PTRW_TOKEN TOKEN('w')
#define POST_INC_TOKEN TOKEN('p')
#define POST_DEC_TOKEN TOKEN('k')
#define OPEN_PAREN_TOKEN TOKEN('(')