diff --git a/compiler/ast.nim b/compiler/ast.nim
index d8f9fc36c..a342e1ea7 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -10,223 +10,38 @@
# abstract syntax tree + symbol table
import
- msgs, hashes, nversion, options, strutils, securehash, ropes, idents,
- intsets, idgen
+ lineinfos, options, ropes, idents, int128, wordrecg
-type
- TCallingConvention* = enum
- ccDefault, # proc has no explicit calling convention
- ccStdCall, # procedure is stdcall
- ccCDecl, # cdecl
- ccSafeCall, # safecall
- ccSysCall, # system call
- ccInline, # proc should be inlined
- ccNoInline, # proc should not be inlined
- ccFastCall, # fastcall (pass parameters in registers)
- ccClosure, # proc has a closure
- ccNoConvention # needed for generating proper C procs sometimes
+import std/[tables, hashes]
+from std/strutils import toLowerAscii
-const
- CallingConvToStr*: array[TCallingConvention, string] = ["", "stdcall",
- "cdecl", "safecall", "syscall", "inline", "noinline", "fastcall",
- "closure", "noconv"]
+when defined(nimPreviewSlimSystem):
+ import std/assertions
+
+export int128
+
+import nodekinds
+export nodekinds
type
- TNodeKind* = enum # order is extremely important, because ranges are used
- # to check whether a node belongs to a certain class
- nkNone, # unknown node kind: indicates an error
- # Expressions:
- # Atoms:
- nkEmpty, # the node is empty
- nkIdent, # node is an identifier
- nkSym, # node is a symbol
- nkType, # node is used for its typ field
-
- nkCharLit, # a character literal ''
- nkIntLit, # an integer literal
- nkInt8Lit,
- nkInt16Lit,
- nkInt32Lit,
- nkInt64Lit,
- nkUIntLit, # an unsigned integer literal
- nkUInt8Lit,
- nkUInt16Lit,
- nkUInt32Lit,
- nkUInt64Lit,
- nkFloatLit, # a floating point literal
- nkFloat32Lit,
- nkFloat64Lit,
- nkFloat128Lit,
- nkStrLit, # a string literal ""
- nkRStrLit, # a raw string literal r""
- nkTripleStrLit, # a triple string literal """
- nkNilLit, # the nil literal
- # end of atoms
- nkMetaNode_Obsolete, # difficult to explain; represents itself
- # (used for macros)
- nkDotCall, # used to temporarily flag a nkCall node;
- # this is used
- # for transforming ``s.len`` to ``len(s)``
-
- nkCommand, # a call like ``p 2, 4`` without parenthesis
- nkCall, # a call like p(x, y) or an operation like +(a, b)
- nkCallStrLit, # a call with a string literal
- # x"abc" has two sons: nkIdent, nkRStrLit
- # x"""abc""" has two sons: nkIdent, nkTripleStrLit
- nkInfix, # a call like (a + b)
- nkPrefix, # a call like !a
- nkPostfix, # something like a! (also used for visibility)
- nkHiddenCallConv, # an implicit type conversion via a type converter
-
- nkExprEqExpr, # a named parameter with equals: ''expr = expr''
- nkExprColonExpr, # a named parameter with colon: ''expr: expr''
- nkIdentDefs, # a definition like `a, b: typeDesc = expr`
- # either typeDesc or expr may be nil; used in
- # formal parameters, var statements, etc.
- nkVarTuple, # a ``var (a, b) = expr`` construct
- nkPar, # syntactic (); may be a tuple constructor
- nkObjConstr, # object constructor: T(a: 1, b: 2)
- nkCurly, # syntactic {}
- nkCurlyExpr, # an expression like a{i}
- nkBracket, # syntactic []
- nkBracketExpr, # an expression like a[i..j, k]
- nkPragmaExpr, # an expression like a{.pragmas.}
- nkRange, # an expression like i..j
- nkDotExpr, # a.b
- nkCheckedFieldExpr, # a.b, but b is a field that needs to be checked
- nkDerefExpr, # a^
- nkIfExpr, # if as an expression
- nkElifExpr,
- nkElseExpr,
- nkLambda, # lambda expression
- nkDo, # lambda block appering as trailing proc param
- nkAccQuoted, # `a` as a node
-
- nkTableConstr, # a table constructor {expr: expr}
- nkBind, # ``bind expr`` node
- nkClosedSymChoice, # symbol choice node; a list of nkSyms (closed)
- nkOpenSymChoice, # symbol choice node; a list of nkSyms (open)
- nkHiddenStdConv, # an implicit standard type conversion
- nkHiddenSubConv, # an implicit type conversion from a subtype
- # to a supertype
- nkConv, # a type conversion
- nkCast, # a type cast
- nkStaticExpr, # a static expr
- nkAddr, # a addr expression
- nkHiddenAddr, # implicit address operator
- nkHiddenDeref, # implicit ^ operator
- nkObjDownConv, # down conversion between object types
- nkObjUpConv, # up conversion between object types
- nkChckRangeF, # range check for floats
- nkChckRange64, # range check for 64 bit ints
- nkChckRange, # range check for ints
- nkStringToCString, # string to cstring
- nkCStringToString, # cstring to string
- # end of expressions
-
- nkAsgn, # a = b
- nkFastAsgn, # internal node for a fast ``a = b``
- # (no string copy)
- nkGenericParams, # generic parameters
- nkFormalParams, # formal parameters
- nkOfInherit, # inherited from symbol
-
- nkImportAs, # a 'as' b in an import statement
- nkProcDef, # a proc
- nkMethodDef, # a method
- nkConverterDef, # a converter
- nkMacroDef, # a macro
- nkTemplateDef, # a template
- nkIteratorDef, # an iterator
-
- nkOfBranch, # used inside case statements
- # for (cond, action)-pairs
- nkElifBranch, # used in if statements
- nkExceptBranch, # an except section
- nkElse, # an else part
- nkAsmStmt, # an assembler block
- nkPragma, # a pragma statement
- nkPragmaBlock, # a pragma with a block
- nkIfStmt, # an if statement
- nkWhenStmt, # a when expression or statement
- nkForStmt, # a for statement
- nkParForStmt, # a parallel for statement
- nkWhileStmt, # a while statement
- nkCaseStmt, # a case statement
- nkTypeSection, # a type section (consists of type definitions)
- nkVarSection, # a var section
- nkLetSection, # a let section
- nkConstSection, # a const section
- nkConstDef, # a const definition
- nkTypeDef, # a type definition
- nkYieldStmt, # the yield statement as a tree
- nkDefer, # the 'defer' statement
- nkTryStmt, # a try statement
- nkFinally, # a finally section
- nkRaiseStmt, # a raise statement
- nkReturnStmt, # a return statement
- nkBreakStmt, # a break statement
- nkContinueStmt, # a continue statement
- nkBlockStmt, # a block statement
- nkStaticStmt, # a static statement
- nkDiscardStmt, # a discard statement
- nkStmtList, # a list of statements
- nkImportStmt, # an import statement
- nkImportExceptStmt, # an import x except a statement
- /*
* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
* See LICENSE file for license details.
*/
#include "dwm.h"
#include <stdlib.h>
#include <string.h>
#include <X11/Xatom.h>
#include <X11/Xutil.h>
/* static functions */
static void
detachstack(Client *c) {
Client **tc;
for(tc=&stack; *tc && *tc != c; tc=&(*tc)->snext);
*tc = c->snext;
}
static void
grabbuttons(Client *c, Bool focused) {
XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
if(focused) {
XGrabButton(dpy, Button1, MODKEY, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button1, MODKEY | LockMask, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button1, MODKEY | numlockmask, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button1, MODKEY | numlockmask | LockMask, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button2, MODKEY, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button2, MODKEY | LockMask, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button2, MODKEY | numlockmask, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button2, MODKEY | numlockmask | LockMask, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button3, MODKEY, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button3, MODKEY | LockMask, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button3, MODKEY | numlockmask, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button3, MODKEY | numlockmask | LockMask, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
}
else
XGrabButton(dpy, AnyButton, AnyModifier, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
}
static void
resizetitle(Client *c) {
c->tw = textw(c->name);
if(c->tw > c->w)
c->tw = c->w + 2;
c->tx = c->x + c->w - c->tw + 2;
c->ty = c->y;
if(isvisible(c))
XMoveResizeWindow(dpy, c->twin, c->tx, c->ty, c->tw, c->th);
else
XMoveResizeWindow(dpy, c->twin, c->tx + 2 * sw, c->ty, c->tw, c->th);
}
static int
xerrordummy(Display *dsply, XErrorEvent *ee) {
return 0;
}
/* extern functions */
void
ban(Client *c) {
XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
XMoveWindow(dpy, c->twin, c->tx + 2 * sw, c->ty);
}
void
focus(Client *c) {
Client *old;
if(!issel || (c && !isvisible(c)))
return;
if(!sel)
sel = c;
else if(sel != c) {
if(maximized)
togglemax(NULL);
old = sel;
sel = c;
if(old) {
grabbuttons(old, False);
drawtitle(old);
}
}
if(c) {
detachstack(c);
c->snext = stack;
stack = c;
grabbuttons(c, True);
drawtitle(c);
XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
}
else
XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
}
Client *
getclient(Window w) {
Client *c;
for(c = clients; c; c = c->next)
if(c->win == w)
return c;
return NULL;
}
Client *
getctitle(Window w) {
Client *c;
for(c = clients; c; c = c->next)
if(c->twin == w)
return c;
return NULL;
}
void
gravitate(Client *c, Bool invert) {
int dx = 0, dy = 0;
switch(c->grav) {
default:
break;
case StaticGravity:
case NorthWestGravity:
case NorthGravity:
case NorthEastGravity:
dy = c->border;
break;
case EastGravity:
case CenterGravity:
case WestGravity:
dy = -(c->h / 2) + c->border;
break;
case SouthEastGravity:
case SouthGravity:
case SouthWestGravity:
dy = -(c->h);
break;
}
switch (c->grav) {
default:
break;
case StaticGravity:
case NorthWestGravity:
case WestGravity:
case SouthWestGravity:
dx = c->border;
break;
case NorthGravity:
case CenterGravity:
case SouthGravity:
dx = -(c->w / 2) + c->border;
break;
case NorthEastGravity:
case EastGravity:
case SouthEastGravity:
dx = -(c->w + c->border);
break;
}
if(invert) {
dx = -dx;
dy = -dy;
}
c->x += dx;
c->y += dy;
}
void
killclient(Arg *arg) {
if(!sel)
return;
if(sel->proto & PROTODELWIN)
sendevent(sel->win, wmatom[WMProtocols], wmatom[WMDelete]);
else
XKillClient(dpy, sel->win);
}
void
manage(Window w, XWindowAttributes *wa) {
Client *c;
Window trans;
XSetWindowAttributes twa;
c = emallocz(sizeof(Client));
c->tags = emallocz(ntags * sizeof(Bool));
c->win = w;
c->x = c->tx = wa->x;
c->y = c->ty = wa->y;
c->w = c->tw = wa->width;
c->h = wa->height;
c->th = bh;
c->border = 0;
updatesize(c);
if(c->x + c->w + 2 > sw)
c->x = sw - c->w - 2;
if(c->x < 0)
c->x = 0;
if(c->y + c->h + 2 > sh)
c->y = sh - c->h - 2;
if(c->h != sh && c->y < bh)
c->y = bh;
c->proto = getproto(c->win);
XSelectInput(dpy, c->win,
StructureNotifyMask | PropertyChangeMask | EnterWindowMask);
XGetTransientForHint(dpy, c->win, &trans);
twa.override_redirect = 1;
twa.background_pixmap = ParentRelative;
twa.event_mask = ExposureMask | EnterWindowMask;
c->twin = XCreateWindow(dpy, root, c->tx, c->ty, c->tw, c->th,
0, DefaultDepth(dpy, screen), CopyFromParent,
DefaultVisual(dpy, screen),
CWOverrideRedirect | CWBackPixmap | CWEventMask, &twa);
grabbuttons(c, False);
settags(c, getclient(trans));
if(!c->isfloat)
c->isfloat = trans
|| (c->maxw && c->minw &&
c->maxw == c->minw && c->maxh == c->minh);
if(clients)
clients->prev = c;
c->next = clients;
c->snext = stack;
stack = clients = c;
updatetitle(c);
ban(c);
XMapWindow(dpy, c->win);
XMapWindow(dpy, c->twin);
if(isvisible(c))
focus(c);
arrange(NULL);
}
void
resize(Client *c, Bool sizehints, Corner sticky) {
int bottom = c->y + c->h;
int right = c->x + c->w;
XWindowChanges wc;
if(sizehints) {
if(c->incw)
c->w -= (c->w - c->basew) % c->incw;
if(c->inch)
c->h -= (c->h - c->baseh) % c->inch;
if(c->minw && c->w < c->minw)
c->w = c->minw;
if(c->minh && c->h < c->minh)
c->h = c->minh;
if(c->maxw && c->w > c->maxw)
c->w = c->maxw;
if(c->maxh && c->h > c->maxh)
c->h = c->maxh;
}
if(sticky == TopRight || sticky == BotRight)
c->x = right - c->w;
if(sticky == BotLeft || sticky == BotRight)
c->y = bottom - c->h;
/* offscreen appearance fixes */
if(c->x + c->w < 0)
c->x = 0;
if(c->y + c->h < bh)
c->y = bh;
if(c->x > sw)
c->x = sw - c->w;
if(c->y > sh)
c->y = sh - c->h;
resizetitle(c);
wc.x = c->x;
wc.y = c->y;
wc.width = c->w;
wc.height = c->h;
if(c->w == sw && c->h == sh)
wc.border_width = 0;
else
wc.border_width = 1;
XConfigureWindow(dpy, c->win, CWX | CWY | CWWidth | CWHeight | CWBorderWidth, &wc);
XSync(dpy, False);
}
void
updatesize(Client *c) {
long msize;
XSizeHints size;
if(!XGetWMNormalHints(dpy, c->win, &size, &msize) || !size.flags)
size.flags = PSize;
c->flags = size.flags;
if(c->flags & PBaseSize) {
c->basew = size.base_width;
c->baseh = size.base_height;
}
else
c->basew = c->baseh = 0;
if(c->flags & PResizeInc) {
c->incw = size.width_inc;
c->inch = size.height_inc;
}
else
c->incw = c->inch = 0;
if(c->flags & PMaxSize) {
c->maxw = size.max_width;
c->maxh = size.max_height;
}
else
c->maxw = c->maxh = 0;
if(c->flags & PMinSize) {
c->minw = size.min_width;
c->minh = size.min_height;
}
else
c->minw = c->minh = 0;
if(c->flags & PWinGravity)
c->grav = size.win_gravity;
else
c->grav = NorthWestGravity;
}
void
updatetitle(Client *c) {
char **list = NULL;
int n;
XTextProperty name;
name.nitems = 0;
c->name[0] = 0;
XGetTextProperty(dpy, c->win, &name, netatom[NetWMName]);
if(!name.nitems)
XGetWMName(dpy, c->win, &name);
if(!name.nitems)
return;
if(name.encoding == XA_STRING)
strncpy(c->name, (char *)name.value, sizeof(c->name));
else {
if(XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success
&& n > 0 && *list)
{
strncpy(c->name, *list, sizeof(c->name));
XFreeStringList(list);
}
}
XFree(name.value);
resizetitle(c);
}
void
togglemax(Arg *arg) {
int ox, oy, ow, oh;
Client *c;
XEvent ev;
if(!sel)
return;
if((maximized = !maximized)) {
ox = sel->x;
oy = sel->y;
ow = sel->w;
oh = sel->h;
sel->x = sx;
sel->y = sy + bh;
sel->w = sw - 2;
sel->h = sh - 2 - bh;
restack();
for(c = getnext(clients); c; c = getnext(c->next))
if(c != sel)
ban(c);
resize(sel, arrange == dofloat, TopLeft);
sel->x = ox;
sel->y = oy;
sel->w = ow;
sel->h = oh;
}
else
arrange(NULL);
while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
}
void
unmanage(Client *c) {
Client *nc;
/* The server grab construct avoids race conditions. */
XGrabServer(dpy);
XSetErrorHandler(xerrordummy);
detach(c);
detachstack(c);
if(sel == c) {
for(nc = stack; nc && !isvisible(nc); nc = nc->snext);
focus(nc);
}
XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
XDestroyWindow(dpy, c->twin);
free(c->tags);
free(c);
XSync(dpy, False);
XSetErrorHandler(xerror);
XUngrabServer(dpy);
arrange(NULL);
}
|