505 lines
26 KiB
C
505 lines
26 KiB
C
// The MIT License (MIT)
|
|
//
|
|
// Copyright (C) 2026 Scott Duensing
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
// of this software and associated documentation files (the "Software"), to
|
|
// deal in the Software without restriction, including without limitation the
|
|
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
// sell copies of the Software, and to permit persons to whom the Software is
|
|
// furnished to do so, subject to the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included in
|
|
// all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
// IN THE SOFTWARE.
|
|
|
|
// front.h -- DVX BASIC compiler internals shared by the front-end passes
|
|
//
|
|
// parse*.c tokens -> syntax tree of one unit (and the declaration pass)
|
|
// resolve*.c names -> symbols, built-ins, controls; semantic checks
|
|
// typecheck.c static types and implicit conversions
|
|
// fold.c constant folding (CONST values, literal subexpressions)
|
|
// gen*.c tree -> p-code
|
|
// compiler.c the driver: declaration pass, unit loop, module tables
|
|
//
|
|
// Embeddable: no DVX dependencies, pure C.
|
|
|
|
#ifndef DVXBASIC_FRONT_H
|
|
#define DVXBASIC_FRONT_H
|
|
|
|
#include "compiler.h"
|
|
#include "ast.h"
|
|
#include "scope.h"
|
|
#include "lexer.h"
|
|
#include "codegen.h"
|
|
#include "opcodes.h"
|
|
#include "../runtime/vm.h"
|
|
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
|
|
// Error message sizes: the stored message ("Line N, Col M: text") and
|
|
// the text before the prefix is added.
|
|
#define BAS_COMPILE_ERROR_LEN 1024
|
|
#define BAS_ERROR_TEXT_LEN 512
|
|
|
|
// Letters DEFINT .. DEFSTR cover (A-Z), and a letter with no DEFxxx.
|
|
#define BAS_DEFTYPE_LETTERS ('Z' - 'A' + 1)
|
|
#define BAS_DEFTYPE_NONE 0xFF
|
|
|
|
// Recursion guards: nested expressions and blocks each cost a dozen C
|
|
// stack frames, and the DOS stack is small.
|
|
#define BAS_MAX_EXPR_DEPTH 64
|
|
#define BAS_MAX_BLOCK_DEPTH 32
|
|
|
|
// blockDepth while a top-level unit's own statement is parsed (a
|
|
// procedure must be one: its scope lives in the unit arena).
|
|
#define BAS_UNIT_BLOCK_DEPTH 1
|
|
|
|
// Longest TYPE field chain in a store target (a.b.c ...).
|
|
#define BAS_MAX_FIELD_CHAIN BAS_LAYOUT_MAX_DEPTH
|
|
|
|
// The member class of an object the source names directly (a control or
|
|
// a form, not an object variable): its methods take their arguments by
|
|
// value.
|
|
#define BAS_CLASS_HOST (-3)
|
|
|
|
// BASIC's TRUE as an integer.
|
|
#define BAS_TRUE_INT (-1)
|
|
|
|
// DEF FN function names start with FN.
|
|
#define BAS_DEFFN_PREFIX "FN"
|
|
|
|
// Form / PictureBox drawing methods with QBasic statement syntax, and
|
|
// the form methods a two-part name.Show / name.Hide statement means.
|
|
#define BAS_METHOD_CIRCLE "Circle"
|
|
#define BAS_METHOD_LINE "Line"
|
|
#define BAS_METHOD_PRINT "Print"
|
|
#define BAS_METHOD_PSET "PSet"
|
|
#define BAS_METHOD_SCALE "Scale"
|
|
#define BAS_METHOD_SHOW "Show"
|
|
#define BAS_METHOD_HIDE "Hide"
|
|
|
|
// A file-private name (Private CONST / ENUM outside class modules) is the
|
|
// name, this separator (no identifier holds it) and the file's number.
|
|
#define BAS_FILE_PRIVATE_SEP "|"
|
|
|
|
// basDeclareEnumName's file for a name every file sees.
|
|
#define BAS_FILE_PUBLIC (-1)
|
|
|
|
// Words the parser reads by their text (identifiers, not reserved).
|
|
#define BAS_KW_COMPARE "COMPARE"
|
|
#define BAS_KW_FRIEND "FRIEND"
|
|
#define BAS_KW_IMPLEMENTS "IMPLEMENTS"
|
|
#define BAS_KW_TEXT "TEXT"
|
|
|
|
// Built-ins the parser calls by these names (BasBuiltinT.name), which no
|
|
// identifier can spell: LIKE and ERROR are reserved words, a name holds
|
|
// no '.'.
|
|
#define BAS_BUILTIN_LIKE "LIKE"
|
|
#define BAS_BUILTIN_ERROR "ERROR"
|
|
#define BAS_BUILTIN_ERR_DESCRIPTION "ERR.DESCRIPTION"
|
|
#define BAS_BUILTIN_ERR_SOURCE "ERR.SOURCE"
|
|
|
|
// ARRAY(...), which the resolver builds itself (a program's own Array
|
|
// procedure or variable comes first).
|
|
#define BAS_ARRAY_FUNC "ARRAY"
|
|
|
|
// Err's members the parser reads by their text.
|
|
#define BAS_ERR_MEMBER_CLEAR "CLEAR"
|
|
#define BAS_ERR_MEMBER_DESCRIPTION "DESCRIPTION"
|
|
#define BAS_ERR_MEMBER_NUMBER "NUMBER"
|
|
#define BAS_ERR_MEMBER_RAISE "RAISE"
|
|
#define BAS_ERR_MEMBER_SOURCE "SOURCE"
|
|
|
|
// Arguments of the two-argument statements and built-ins (FILECOPY,
|
|
// NAME, SETATTR, SEEK, LIKE ...).
|
|
#define BAS_PAIR_ARGS 2
|
|
|
|
// ST_ONERROR's ival: ON ERROR RESUME NEXT (0: ON ERROR GOTO).
|
|
#define BAS_ON_ERROR_RESUME_NEXT 1
|
|
|
|
// ST_LABEL ival: a QBasic line number (its value in ival2), which ERL reports
|
|
#define BAS_LABEL_LINE_NUMBER 1
|
|
|
|
|
|
// MsgBox: the OK button only (vbOKOnly, the default flags).
|
|
#define BAS_MSGBOX_OK_ONLY 0x0000
|
|
|
|
// The error for a name after AS that is no type.
|
|
#define BAS_TYPE_EXPECTED "Expected type name (Integer, Long, Single, Double, String, Boolean, Date, Variant, Control, Form, Object, Collection, TYPE, ENUM or class name)"
|
|
|
|
// Types named by identifiers rather than reserved words.
|
|
#define BAS_DATE_TYPE_NAME "DATE"
|
|
#define BAS_BYTE_TYPE_NAME "BYTE"
|
|
#define BAS_CURRENCY_TYPE_NAME "CURRENCY"
|
|
#define BAS_VARIANT_TYPE_NAME "VARIANT"
|
|
#define BAS_COLLECTION_TYPE_NAME "COLLECTION"
|
|
|
|
// The Collection class as messages name it.
|
|
#define BAS_COLLECTION_DISPLAY_NAME "Collection"
|
|
|
|
// Built-in function flags.
|
|
#define BI_PURE 0x01 // result depends on the arguments alone: allowed in constant expressions
|
|
#define BI_FOLD 0x02 // folded in ordinary code when its arguments are literals
|
|
#define BI_OBJECT_ARG 0x04 // the first argument is an object (a bare control or form name is the object)
|
|
|
|
// The built-in function a statement may call too (CallByName obj, ...).
|
|
#define BAS_CALLBYNAME_NAME "CallByName"
|
|
|
|
// A built-in function (BasBuiltinT table in resolveExpr.c). An
|
|
// OP_BUILTIN entry names its BasBuiltinFnE in func and takes its argument
|
|
// counts from basBuiltinArity.
|
|
typedef struct {
|
|
const char *name;
|
|
uint8_t opcode;
|
|
uint8_t func;
|
|
uint8_t minArgs;
|
|
uint8_t maxArgs;
|
|
uint8_t resultType; // BAS_TYPE_* the result always has (BAS_NODE_TYPE_UNKNOWN: depends)
|
|
uint8_t flags; // BI_*
|
|
uint8_t nullMask; // arguments (BAS_NULL_ARG_*) whose Null makes the result Null: VB's Variant forms (Left, Mid ...); 0: none
|
|
const char *const *argNames; // VB's names of its arguments (Name:=value), NULL-terminated; NULL: none given by name
|
|
} BasBuiltinT;
|
|
|
|
// How an early-bound member is used (basBindMember).
|
|
typedef enum {
|
|
BAS_ACCESS_READ, // obj.name: its value (no argument list)
|
|
BAS_ACCESS_VALUE, // obj.name(args) in an expression
|
|
BAS_ACCESS_STATEMENT, // obj.name args / obj.name(args) as a statement
|
|
BAS_ACCESS_LET, // obj.name(args) = value
|
|
BAS_ACCESS_SET // Set obj.name(args) = value
|
|
} BasAccessE;
|
|
|
|
// How an unresolved name is being used (resolver).
|
|
typedef enum {
|
|
BAS_USE_VALUE, // its value
|
|
BAS_USE_OBJECT, // an object is expected (SET value, IS / TypeOf operand, object parameter)
|
|
BAS_USE_MEMBERBASE // name.member
|
|
} BasUseE;
|
|
|
|
// Deferred argument forms of the drawing methods (obj.Line ...), read
|
|
// once the resolver knows whether obj is a class instance.
|
|
typedef enum {
|
|
BAS_DEFER_ARGS, // comma-separated method arguments
|
|
BAS_DEFER_DRAWING // the method's QBasic statement syntax (Print items, Line / Circle / PSet blocks, Scale rectangle)
|
|
} BasDeferModeE;
|
|
|
|
// How an assignment stores (BasStmtT.ival2 of ST_ASSIGN).
|
|
typedef enum {
|
|
BAS_STORE_PLAIN, // the value replaces what the target holds
|
|
BAS_STORE_APPEND, // s = s + x / s = s & x on a STRING variable: x appended in place (OP_STR_APPEND); ival = the operator
|
|
BAS_STORE_RECORD // a TYPE value copied into the record the target holds (BAS_FN_RECORD_ASSIGN)
|
|
} BasStoreE;
|
|
|
|
// A change the resolver made to a symbol in the middle of a unit (see
|
|
// basSymChange): what it was before and after statement at.
|
|
typedef struct {
|
|
const BasNodeT *at;
|
|
BasSymT *sym;
|
|
uint32_t beforeFlags;
|
|
uint32_t afterFlags;
|
|
int32_t beforeUdtTypeId;
|
|
int32_t afterUdtTypeId;
|
|
uint8_t beforeType;
|
|
uint8_t afterType;
|
|
} BasSymChangeT;
|
|
|
|
// A loop or SELECT the generator is inside.
|
|
typedef struct {
|
|
int32_t *exitPatches; // stb_ds: EXIT jumps to land after the loop
|
|
int32_t selectBase; // SELECT depth at the loop's start (EXIT pops the ones opened since)
|
|
bool isFor; // FOR / FOR EACH (else DO / WHILE)
|
|
bool isForEach; // no VM FOR frame to drop on EXIT FOR
|
|
} BasGenLoopT;
|
|
|
|
struct BasCompilerS {
|
|
// Source and tokens
|
|
const char *source;
|
|
int32_t sourceLen;
|
|
BasLexerT lex;
|
|
int32_t prevLine; // line of the previous token (errors at the end of a line)
|
|
|
|
// First error
|
|
char error[BAS_COMPILE_ERROR_LEN];
|
|
bool hasError;
|
|
int32_t errorLine;
|
|
int32_t errorCol;
|
|
|
|
// Memory: module-lifetime data and the unit being compiled
|
|
BasArenaT modArena;
|
|
BasArenaT unitArena;
|
|
|
|
// Parser context (syntax only)
|
|
int32_t exprDepth;
|
|
int32_t blockDepth;
|
|
bool parseInClass; // between BEGINCLASS and ENDCLASS
|
|
bool parseInProc; // inside a SUB / FUNCTION / Property body
|
|
bool parseProcIsFunction; // ... a FUNCTION or Property Get (its name sets its result)
|
|
bool parseProcIsStatic; // ... declared STATIC (its DIMs declare STATIC variables)
|
|
bool parseInDeclareLib; // inside a DECLARE LIBRARY block (BINARY STRING allowed)
|
|
const char *parseProcName; // the procedure being parsed (its own name sets its result)
|
|
const char *parseClassName; // the class module being parsed (module arena; parseInClass)
|
|
BasWithT *parseWith; // the innermost WITH block being parsed (its '.name's)
|
|
|
|
// Symbols
|
|
BasScopeTabT moduleTab; // globals, procedures, constants, TYPE / ENUM / class names
|
|
BasScopeTabT moduleLabels;
|
|
BasScopeTabT formTab; // the current form's variables (inForm)
|
|
BasScopeTabT localTab; // the current procedure's parameters and locals (inProc)
|
|
BasScopeTabT localLabels;
|
|
BasTypeDefT **typeDefs; // stb_ds, indexed by TYPE id
|
|
BasClassDefT *classes; // stb_ds, indexed by class number
|
|
BasWithEventsDefT *withEvents; // stb_ds, binding number order
|
|
const char **formNames; // stb_ds, every BEGINFORM name (declaration pass)
|
|
BasSymT **moduleVars; // stb_ds, module / form / member variables in creation order (debug info)
|
|
BasMemberVarDeclT *memberVarDecls; // stb_ds, class member variables the declaration pass read (registered at its end)
|
|
BasMemberPatchT *memberPatches; // stb_ds, early-bound member operands to fill in at the end
|
|
|
|
// Scope state (resolver, in source order)
|
|
bool inForm;
|
|
bool inClass;
|
|
bool inProc;
|
|
bool inDefFn; // a DEF FN body: undeclared names are module variables
|
|
bool inConstExpr; // a constant expression: only constants may be named
|
|
const char *formName; // current form ("" outside)
|
|
int32_t fileIdx; // the project file being compiled (BEGINMODULE / BEGINFORM / BEGINCLASS block; 0 outside them): where a Private CONST / ENUM is seen
|
|
int32_t outerFileIdx; // fileIdx around the BEGINFORM / BEGINCLASS block being compiled (a class inside a project's module goes back to the module's)
|
|
int32_t fileCount; // file numbers given out so far
|
|
int32_t filePrivates; // file-private names declared (lookups try the file's own first while there are any)
|
|
int32_t classIdx; // current class (inClass)
|
|
BasSymT *curProc; // procedure being compiled (inProc)
|
|
const char *curProcName; // its name as written (its result is set by it)
|
|
uint8_t curProcKind; // its BasMemberKindE
|
|
bool curProcStatic; // it was declared STATIC: its implicit variables are STATIC
|
|
int32_t nextGlobalSlot;
|
|
int32_t nextFormSlot;
|
|
int32_t nextMemberSlot;
|
|
int32_t nextLocalSlot;
|
|
int32_t hiddenCount; // names of compiler variables
|
|
uint8_t defType[BAS_DEFTYPE_LETTERS];
|
|
int32_t optionBase;
|
|
bool optionExplicit;
|
|
bool compareText; // OPTION COMPARE TEXT (constant expressions)
|
|
|
|
// Resolver bookkeeping inside a procedure (or the module body)
|
|
int32_t forDepth;
|
|
int32_t doDepth;
|
|
int32_t selectDepth;
|
|
int32_t lastLabelDepth; // SELECT depth at the label defined last (RETURN pops the ones opened since)
|
|
int32_t savedForDepth; // the module body's bookkeeping while a procedure is compiled
|
|
int32_t savedDoDepth;
|
|
int32_t savedSelectDepth;
|
|
int32_t savedLabelDepth;
|
|
BasSymChangeT *symChanges; // stb_ds: the current unit's symbol changes, in source order
|
|
|
|
// Code generation
|
|
BasCodeGenT cg;
|
|
int32_t initJmpAddr; // JMP over a form / class set-up block (-1: none)
|
|
int32_t initCodeStart; // first byte of that block
|
|
int32_t procSkipJump; // JMP over the procedures defined since the last module code (-1: none)
|
|
int32_t *tempSlots; // stb_ds: compiler temporaries of the module code (global / form slots)
|
|
int32_t *procTempSlots; // stb_ds: compiler temporaries of the procedure being generated (local slots)
|
|
int32_t tempUsed; // temporaries the current statement holds
|
|
BasGenLoopT *loops; // stb_ds: open loops, innermost last
|
|
int32_t genSelectDepth; // SELECT test values on the eval stack
|
|
int32_t *exitProcPatches; // stb_ds: EXIT SUB / FUNCTION / PROPERTY jumps
|
|
int32_t debugProcCount; // procedures emitted (debugger procIndex)
|
|
|
|
BasVmT *constVm; // evaluates constant expressions (made on first use)
|
|
|
|
const BasCtrlValidatorT *validator;
|
|
};
|
|
|
|
// ============================================================
|
|
// Errors (compiler.c)
|
|
// ============================================================
|
|
|
|
// Records the first error at line / col (col 0: not known).
|
|
void basErrorAt(BasCompilerT *c, int32_t line, int32_t col, const char *fmt, ...);
|
|
|
|
// Records the first error at a node.
|
|
void basErrorNode(BasCompilerT *c, const BasNodeT *n, const char *fmt, ...);
|
|
|
|
// ============================================================
|
|
// Parser (parse.c, parseExpr.c, parseStmt.c, parseDecl.c)
|
|
// ============================================================
|
|
|
|
void basParseAdvance(BasCompilerT *c);
|
|
BasTokenTypeE basParseAfterParens(BasLexerT *lex);
|
|
BasNodeT *basParseArgList(BasCompilerT *c, int32_t *outArgc);
|
|
bool basParseAtEnd(BasCompilerT *c);
|
|
BasNodeT *basParseAttribute(BasCompilerT *c);
|
|
BasNodeT *basParseBareArgs(BasCompilerT *c, int32_t *outArgc);
|
|
BasNodeT *basParseBuiltinCall(BasCompilerT *c, const char *name, BasNodeT *args, int32_t argc, int32_t line, int32_t col);
|
|
BasNodeT *basParseChain(BasCompilerT *c, BasNodeT *base, bool statement);
|
|
bool basParseCheck(const BasCompilerT *c, BasTokenTypeE type);
|
|
bool basParseCheckWord(const BasCompilerT *c, const char *word);
|
|
BasNodeT *basParseCurLit(BasCompilerT *c, int64_t scaled);
|
|
void basParseDeclarations(BasCompilerT *c);
|
|
BasNodeT *basParseDeclStatement(BasCompilerT *c);
|
|
BasNodeT *basParseDeferredArgs(BasCompilerT *c, BasStmtT *call, BasDeferModeE mode, int32_t *outArgc);
|
|
void basParseError(BasCompilerT *c, const char *fmt, ...);
|
|
void basParseErrorExpected(BasCompilerT *c, const char *what);
|
|
BasNodeT *basParseEvent(BasCompilerT *c);
|
|
void basParseExpect(BasCompilerT *c, BasTokenTypeE type);
|
|
void basParseExpectEnd(BasCompilerT *c);
|
|
BasNodeT *basParseExpr(BasCompilerT *c);
|
|
bool basParseFriendAhead(const BasCompilerT *c);
|
|
BasNodeT *basParseFriendProc(BasCompilerT *c);
|
|
BasNodeT *basParseInputBoxArgs(BasCompilerT *c, int32_t *outArgc);
|
|
BasNodeT *basParseIntLit(BasCompilerT *c, int32_t value);
|
|
BasNodeT *basParseIntrinsic(BasCompilerT *c, uint8_t opcode, BasNodeT *args, int32_t argc, int32_t operand);
|
|
BasNodeT *basParseLValue(BasCompilerT *c, bool allowFields);
|
|
bool basParseMatch(BasCompilerT *c, BasTokenTypeE type);
|
|
bool basParseMatchEnd(BasCompilerT *c, BasTokenTypeE kw);
|
|
BasNodeT *basParseMsgBoxArgs(BasCompilerT *c, int32_t *outArgc);
|
|
bool basParseNameFollows(BasCompilerT *c, bool anyWord);
|
|
BasNodeT *basParseNode(BasCompilerT *c, int32_t size, uint8_t kind);
|
|
BasNodeT *basParseObjectOperand(BasCompilerT *c, BasNodeT *operand);
|
|
BasTokenTypeE basParsePeekAfterParens(const BasCompilerT *c);
|
|
BasProcT *basParseProcHeader(BasCompilerT *c, uint8_t memberKind, bool memberName);
|
|
void basParseSkipNewlines(BasCompilerT *c);
|
|
BasNodeT *basParseStatement(BasCompilerT *c);
|
|
BasNodeT *basParseStrLit(BasCompilerT *c, const char *text, int32_t len);
|
|
char *basParseTokenName(BasCompilerT *c);
|
|
BasNodeT *basParseUnit(BasCompilerT *c);
|
|
BasNodeT *basParseWithRef(BasCompilerT *c);
|
|
|
|
// ============================================================
|
|
// Resolver (resolve.c, resolveExpr.c)
|
|
// ============================================================
|
|
|
|
BasSymT *basAddGlobalVar(BasCompilerT *c, const char *name, uint8_t dataType);
|
|
BasSymT *basAddLocal(BasCompilerT *c, const char *name, uint8_t kind, uint8_t dataType);
|
|
BasSymT *basAddLocalVar(BasCompilerT *c, const char *name, uint8_t dataType);
|
|
BasSymT *basAddModuleVar(BasCompilerT *c, const char *name, uint8_t dataType);
|
|
BasNodeT *basBindMember(BasCompilerT *c, BasNodeT *obj, int32_t cls, const char *name, BasNodeT *args, int32_t argc, uint8_t access, const BasNodeT *at);
|
|
const BasBuiltinT *basBuiltinFind(const char *name);
|
|
int32_t basClassFind(BasCompilerT *c, const char *name);
|
|
bool basClassKnown(int32_t cls);
|
|
void basCloseProcScope(BasCompilerT *c);
|
|
BasNodeT *basControlNode(BasCompilerT *c, const char *name, const BasNodeT *at);
|
|
bool basConvertsArg(uint8_t dataType, uint8_t paramFlags);
|
|
void basDeclareClass(BasCompilerT *c, const char *name);
|
|
uint8_t basDeclaredStoreType(const BasSymT *sym);
|
|
void basDeclareEnumName(BasCompilerT *c, const char *name, int32_t privateFile);
|
|
void basDeclareForm(BasCompilerT *c, const char *name);
|
|
void basDeclareLibrary(BasCompilerT *c, const BasStmtT *s);
|
|
void basDeclareMemberVars(BasCompilerT *c, const BasStmtT *dim, int32_t classIdx);
|
|
void basDeclareMemberVarsEnd(BasCompilerT *c);
|
|
void basDeclareProc(BasCompilerT *c, BasProcT *proc, int32_t classIdx);
|
|
void basDeclareTypeName(BasCompilerT *c, const char *name);
|
|
void basDeclareUserControlVar(BasCompilerT *c, int32_t classIdx);
|
|
BasSymT *basEnsureVariable(BasCompilerT *c, const char *name, const BasNodeT *at);
|
|
int32_t basExprClass(const BasCompilerT *c, const BasNodeT *n);
|
|
int32_t basExprUdtType(const BasCompilerT *c, const BasNodeT *n);
|
|
int32_t basFieldIndex(const BasTypeDefT *td, const char *name);
|
|
bool basFilePrivateName(const BasCompilerT *c, const char *name, int32_t fileIdx, char *out, int32_t outSize);
|
|
uint8_t basImplicitType(const BasCompilerT *c, const char *name, bool *outTyped);
|
|
bool basIsDefFnName(const char *name);
|
|
bool basIsFormName(const BasCompilerT *c, const char *name);
|
|
bool basLateArgs(BasCompilerT *c, BasCallT *call, BasNodeT *args, int32_t argc, bool byRef);
|
|
BasNodeT *basLoadFormNode(BasCompilerT *c, const char *name, const BasNodeT *at);
|
|
BasSymT *basLookup(BasCompilerT *c, const char *name);
|
|
BasSymT *basLookupModuleVar(BasCompilerT *c, const char *name);
|
|
BasSymT *basLookupProc(BasCompilerT *c, const char *name);
|
|
BasSymT *basModuleFind(const BasCompilerT *c, const char *name);
|
|
BasNodeT *basNamedArgs(BasCompilerT *c, const char *const *names, int32_t count, BasNodeT *args, const BasNodeT *at);
|
|
BasNodeT *basNodeConst(BasCompilerT *c, const BasConstValT *v, const BasNodeT *at);
|
|
BasNodeT *basNodeConv(BasCompilerT *c, BasNodeT *a, uint8_t op, int32_t aux);
|
|
BasNodeT *basNodeCur(BasCompilerT *c, int64_t scaled, const BasNodeT *at);
|
|
BasNodeT *basNodeInt(BasCompilerT *c, int32_t value, uint8_t type, const BasNodeT *at);
|
|
BasNodeT *basNodeIntrinsic(BasCompilerT *c, uint8_t opcode, BasNodeT *args, int32_t argc, int32_t operand, int32_t line, int32_t col);
|
|
BasNodeT *basNodeSpecial(BasCompilerT *c, int32_t kind, const BasNodeT *at);
|
|
BasNodeT *basNodeStr(BasCompilerT *c, const char *text, int32_t len, const BasNodeT *at);
|
|
BasNodeT *basNodeVar(BasCompilerT *c, BasSymT *sym, const BasNodeT *at);
|
|
BasNodeT *basNodeZero(BasCompilerT *c, uint8_t dataType, const BasNodeT *at);
|
|
BasSymT *basPropertyProc(BasCompilerT *c, const char *name, bool isSet);
|
|
bool basQualify(const BasCompilerT *c, int32_t classIdx, const char *name, char *out, int32_t outSize);
|
|
bool basRejectHiddenModuleVar(BasCompilerT *c, const char *name, const BasNodeT *at);
|
|
BasNodeT *basResolveArg(BasCompilerT *c, BasNodeT *arg, bool byRef, uint8_t *outRefType);
|
|
void basResolveBody(BasCompilerT *c, BasNodeT *list);
|
|
BasNodeT *basResolveCallee(BasCompilerT *c, BasCallT *call, bool statement);
|
|
void basResolveDefType(BasCompilerT *c, const BasStmtT *s);
|
|
BasNodeT *basResolveExpr(BasCompilerT *c, BasNodeT *n, uint8_t use);
|
|
BasNodeT *basResolveLValue(BasCompilerT *c, BasNodeT *n, bool allowFields);
|
|
BasNodeT *basResolveMemberParts(BasCompilerT *c, BasMemberT *m, bool isProp, BasNodeT **outObj, int32_t *outClass);
|
|
BasNodeT *basResolveMethodArgs(BasCompilerT *c, BasNodeT *args, int32_t argc, bool byRef);
|
|
void basResolveModuleEnd(BasCompilerT *c);
|
|
BasNodeT *basResolveObjectMember(BasCompilerT *c, BasNodeT *obj, const char *name, int32_t memberClass, uint16_t flags, const BasNodeT *at);
|
|
BasNodeT *basResolveProcArgs(BasCompilerT *c, const BasSymT *sym, BasNodeT *args, int32_t valueParams, const BasNodeT *at, int32_t *outArgc);
|
|
void basResolveStatement(BasCompilerT *c, BasNodeT *s);
|
|
bool basResolveTypeSpec(BasCompilerT *c, const BasTypeSpecT *t, bool prescan, uint8_t *outType, int32_t *outUdt, int32_t *outClass);
|
|
void basResolveUnit(BasCompilerT *c, BasNodeT *unit);
|
|
void basResolveUnitEnd(BasCompilerT *c, BasNodeT *unit);
|
|
BasSymT *basStaticVariable(BasCompilerT *c, const char *name, uint8_t dataType, bool isTyped, int32_t objClass, int32_t fixedLen, const BasNodeT *at, BasSymT **outSlot);
|
|
BasScopeE basStorageScope(const BasSymT *sym);
|
|
void basSymChange(BasCompilerT *c, BasSymT *sym, const BasNodeT *at, uint8_t dataType, int32_t udtTypeId, uint32_t flags);
|
|
void basSymChangesUndo(BasCompilerT *c);
|
|
BasNodeT *basTypedArg(BasCompilerT *c, const char *procName, int32_t idx, uint8_t dataType, bool byVal, BasNodeT *arg);
|
|
BasSymT *basUserControlProc(const BasCompilerT *c, int32_t classIdx, int32_t evt);
|
|
bool basValidateCtrlMember(BasCompilerT *c, const char *ctrlName, const char *member, bool isProp, const BasNodeT *at);
|
|
BasNodeT *basWithObject(BasCompilerT *c, const BasNodeT *ref);
|
|
|
|
// ============================================================
|
|
// Types and folding (typecheck.c, fold.c)
|
|
// ============================================================
|
|
|
|
bool basConstConvert(BasCompilerT *c, BasConstValT *v, uint8_t asType, const char *what, const BasNodeT *at);
|
|
bool basFoldConstExpr(BasCompilerT *c, BasNodeT *expr, BasConstValT *out);
|
|
BasNodeT *basFoldConv(BasCompilerT *c, BasNodeT *value, uint8_t op);
|
|
BasNodeT *basFoldExpr(BasCompilerT *c, BasNodeT *n);
|
|
bool basStartsTyped(uint8_t dataType);
|
|
uint8_t basStaticType(const BasNodeT *n);
|
|
void basTypeUnit(BasCompilerT *c, BasNodeT *unit);
|
|
|
|
// ============================================================
|
|
// Generator (gen.c, genExpr.c, genStmt.c)
|
|
// ============================================================
|
|
|
|
uint8_t basBinaryOpcode(uint8_t tok);
|
|
void basGenAddrOf(BasCompilerT *c, const BasSymT *sym);
|
|
void basGenArgs(BasCompilerT *c, const BasNodeT *list);
|
|
void basGenBody(BasCompilerT *c, const BasNodeT *list);
|
|
void basGenCall(BasCompilerT *c, BasSymT *sym, int32_t argc);
|
|
void basGenDeclaration(BasCompilerT *c, const BasNodeT *s);
|
|
void basGenExpr(BasCompilerT *c, const BasNodeT *n);
|
|
void basGenFlushProcSkip(BasCompilerT *c);
|
|
int32_t basGenJump(BasCompilerT *c, uint8_t op);
|
|
void basGenJumpTo(BasCompilerT *c, uint8_t op, int32_t target);
|
|
void basGenLine(BasCompilerT *c, const BasNodeT *s);
|
|
void basGenLoadTemp(BasCompilerT *c, int32_t slot);
|
|
void basGenLoadVar(BasCompilerT *c, const BasSymT *sym);
|
|
void basGenNew(BasCompilerT *c, const char *name, int32_t objClass);
|
|
void basGenObjMember(BasCompilerT *c, uint8_t op, const BasCallT *call);
|
|
void basGenPatchHere(BasCompilerT *c, int32_t operandPos);
|
|
void basGenPushCStr(BasCompilerT *c, const char *text);
|
|
void basGenPushInt16(BasCompilerT *c, int16_t v);
|
|
void basGenPushSpecial(BasCompilerT *c, uint8_t kind);
|
|
void basGenPushStr(BasCompilerT *c, const char *text, int32_t len);
|
|
void basGenRef(BasCompilerT *c, const BasNodeT *n);
|
|
void basGenSlotRef(BasCompilerT *c, int32_t scope, int32_t slot, uint8_t storeType);
|
|
void basGenStatement(BasCompilerT *c, const BasNodeT *s);
|
|
void basGenStore(BasCompilerT *c, const BasSymT *sym);
|
|
void basGenStoreConv(BasCompilerT *c, uint8_t dataType);
|
|
void basGenStoreFrom(BasCompilerT *c, const BasSymT *sym, uint8_t valueType);
|
|
void basGenStoreRaw(BasCompilerT *c, const BasSymT *sym);
|
|
void basGenStoreSlot(BasCompilerT *c, int32_t scope, int32_t slot, uint8_t conv);
|
|
void basGenStoreTemp(BasCompilerT *c, int32_t slot);
|
|
uint8_t basGenStoreValue(BasCompilerT *c, const BasNodeT *value, uint8_t convType, int32_t fixedLen, int32_t objClass, bool isSet, bool deferConv);
|
|
void basGenSymChanges(BasCompilerT *c, const BasNodeT *at);
|
|
int32_t basGenTemp(BasCompilerT *c);
|
|
void basGenTempRef(BasCompilerT *c);
|
|
void basGenTempReset(BasCompilerT *c);
|
|
bool basGenUdtLayout(BasCompilerT *c, int32_t typeId);
|
|
bool basGenUdtSpec(BasCompilerT *c, int32_t typeId);
|
|
|
|
#endif // DVXBASIC_FRONT_H
|