小编sti*_*ijn的帖子

AST在访问者或节点中遍历?

更新接受了Ira Baxter的回答,因为它指出了我正确的方向:我首先通过开始编译阶段的实现来弄清楚我实际需要什么,很明显很快,节点内的遍历使得这是一个不可能的方法.并非所有节点都应该被访问,其中一些节点的顺序相反(例如,首先是赋值的rhs,因此编译器可以检查类型是否与rhs /运算符匹配).在访问者中进行遍历使得这一切变得非常简单.

在决定对应用程序中使用的迷你语言的处理进行重大修改之前,我正在玩AST和类似的东西.我已经构建了一个Lexer/Parser,可以让AST很好.还有一个访问者,作为具体实现,我创建了一个ASTToOriginal,它只是重新创建原始源文件.最终,还有一些编译器也可以实现Vsisitor并在运行时创建实际的C++代码,所以我想确保一切从一开始就是正确的.虽然现在一切正常,但由于遍历顺序在访问者本身中实现,因此存在一些相似/重复的代码.

在查找更多信息时,似乎某些实现更喜欢在访问对象本身中保留遍历顺序,以便不在每个具体访问者中重复此操作.即便是GoF也只是以同样的方式对此进行了简要的讨论.所以我想尝试这种方法,但很快就陷入了困境.让我解释一下.

示例源代码行和相应的AST节点:

if(t>100?x=1;sety(20,true):x=2)
Conditional
  BinaryOp
    left=Variable [name=t], operator=[>], right=Integer [value=100]
  IfTrue
    Assignment
      left=Variable [name=x], operator=[=], right=Integer [value=1] 
    Method
      MethodName [name=sety], Arguments( Integer [value=20], Boolean [value=true] )
  IfFalse
    Assignment
      left=Variable [name=x], operator=[=], right=Integer [value=1]
Run Code Online (Sandbox Code Playgroud)

一些代码:

class BinaryOp {
  void Accept( Visitor* v ){ v->Visit( this ); }
  Expr* left;
  Op* op;
  Expr* right;
};    
class Variable {
  void Accept( Visitor* v ){ v->Visit( this ); }
  Name* name;
};
class Visitor { //provide basic traversal, terminal …
Run Code Online (Sandbox Code Playgroud)

c++ compiler-construction visitor abstract-syntax-tree

9
推荐指数
1
解决办法
2702
查看次数

将const char**转换为void*?

考虑以下代码:

#include <memory.h>
#include <stdlib.h>

void Foo()
{
  const char ** caps = malloc( sizeof( char * ) );
  memset( caps, 0, sizeof( char * ) );
}
Run Code Online (Sandbox Code Playgroud)

使用gcc 4.9.2 -pedantic编译精细但是cl 18(来自VS2013的那个)warning C4090: 'function' : different 'const' qualifiers在memset行上显示默认选项.

现在caps是一个指向const char指针的指针?所以指针本身不是const因此它应该转换为void*没有问题,我认为,但cl似乎自动const void*从它生成警告.这是对正在发生的事情的正确解释吗?这是非标准行为,对吧?

c gcc pointers visual-c++

9
推荐指数
1
解决办法
1687
查看次数

编写编译器:如何使简单的模板工作?

我有一种语言与C++类似的语法.词法分析器和解析器就位并产生正确的AST.对于最大的部分,后端也已完成.

编译器用于创建类型的基本系统非常简单:所有类型都被认为是内置的,所有实例都是全局的.因此,只有一个简单的映射,它将类型名称与创建变量的方法相匹配,该变量基本上是一个泛型类型,如boost :: any.另一个变量名称为key且Variable为value的映射用作全局范围:

std::map< std::string, std::function< Variable() > typeList;

  //register some types
typeList[ "X" ] = Variable::Create<X>;
typeList[ "Y" ] = CreateInstanceOfY;
....
Run Code Online (Sandbox Code Playgroud)

当编译器获得AST节点进行初始化时就像X myVar;它基本上一样

std::map< std::string, Variable > globalScope;
globalScope[ "myVar" ] = typeList[ "X" ]();
Run Code Online (Sandbox Code Playgroud)

当稍后使用myVar时,可以通过简单的类型调度来访问它

X& x = myVar.GetReference<X>();
Run Code Online (Sandbox Code Playgroud)

现在我想扩展一下并使用简单的模板.假设存在使用向量实现的类型"数组".我可以注册一切像

typeList[ "array<X>" ] = Variable::Create< std::vector< X > >;
Run Code Online (Sandbox Code Playgroud)

但这不是很可管理的,因为它必须对所有组合重复.理想情况下,我需要功能允许写这样的东西:

typeList.CreateTemplateVariable( "array", "X" )
Run Code Online (Sandbox Code Playgroud)

然后会创建一个内部包含std :: vector <X>的Variable实例.我努力了,但无法弄清楚如何做到这一点.也许我只是用简单的类型映射开始了错误的方式,这就是我无法理解它的原因.

所以问题很简单:是否可以这样做?如何?

c++ compiler-construction abstract-syntax-tree c++11

8
推荐指数
1
解决办法
401
查看次数

System.Type的C#反序列化会从已加载的程序集中抛出类型

我有一个a.exe运行良好的应用程序并加载了一个程序集b.dll,如果重要的话,这是一个Prism模块.此dll是从不在路​​径中但a.exe位于所在目录中的目录加载的.

装配由Prism完成,并设置如下:

public class MyModuleCatalog : ComposablePartCatalog
{
  private readonly AggregateCatalog _catalog;

  public MyModuleCatalog()
  {
      //directory Modules is not in the path, but all
      //dependencies of b.dll are, so b.dll gets loaded fine
    var asmCat = new AssemblyCatalog( "Modules/b.dll" );
    _catalog.Catalogs.Add( asmCat );
  }

  public override IQueryable<ComposablePartDefinition> Parts
  {
    get { return _catalog.Parts; }
  }
}

class BootStrapper : MefBootstrapper
{
  ....
  protected override void ConfigureAggregateCatalog()
  {
    base.ConfigureAggregateCatalog();

    AggregateCatalog.Catalogs.Add( new AssemblyCatalog( Assembly.GetExecutingAssembly() ) ); …
Run Code Online (Sandbox Code Playgroud)

c# serialization prism system.type

7
推荐指数
1
解决办法
1852
查看次数

从MSBUILD脚本获取次要版本和主要版本

我正在使用Msbuild来编译和生成.zip文件和安装程序,我需要我的assembyInfo的版本号.

我正在使用此代码.

<Target Name="getversion">
    <GetAssemblyIdentity AssemblyFiles="$(BuildDir)\myprogram.exe">
        <Output TaskParameter="Assemblies" ItemName="fooAssemblyInfo"/>
    </GetAssemblyIdentity>
    <Message Text="Version = %(fooAssemblyInfo.Version)"/>
</Target>
Run Code Online (Sandbox Code Playgroud)

但这会返回Version = 2.0.0.29110,我只需要次要和主要版本.

有没有办法在没有自定义任务的情况下读取assembyInfo.cs信息?

.net msbuild assemblyinfo

7
推荐指数
3
解决办法
7175
查看次数

清除搜索后如何使Solution Explorer恢复到以前的状态?

我目前有一个没有扩展的VS安装,看看它是如何工作的.对于导航意味着大量使用Ctrl+;aka Search Solution Explorer.虽然搜索本身还可以,但它对我来说有一个主要的缺点,这对我来说很麻烦(使用键盘和鼠标):

两个项目的解决方案,一个折叠,一个打开:

在此输入图像描述

使用Ctrl+;并开始键入,直到从折叠项目中找到匹配项

在此输入图像描述

我现在想要的是简单地清除搜索并返回上一个视图.看起来像一个非常标准的要求,不是吗?但似乎没有内置这样的功能.当前命令的问题(解决方案资源管理器工具栏中的按下Esc,单击BackHome按钮)都是一样的:他们有非常讨厌的行为,他们坚持突然贬低先前崩溃项目并跟踪找到的匹配!(顺便提一下Track Active Item in Solution Explorer选项中的选项).从UX的角度来看,这没有任何意义吗?你选择某种'撤消'命令,搜索框清除预期的,但突然之间有一个项目从前一个搜索可见:

在此输入图像描述

因此,如果折叠的项目中有50个项目,那么解决方案资源管理器在视觉上是无用的,因为它会在屏幕上显示您不想看到的内容,更糟糕的是您必须再次手动折叠项目以返回到上一个视图.

有没有解决的办法?我想Back/Home的键盘快捷键可能会有所不同,但命令似乎没有注册.我调查过,EnvDTE80.DTE2.ToolWindows.SolutionExplorer但它没有与此问题有关的属性/方法.在树的某个地方有一个Microsoft.VisualStudio.PlatformUI.SolutionPivotNavigator可能是负责此行为的类,但我不知道如何访问它?

projects-and-solutions visual-studio visual-studio-2012

7
推荐指数
1
解决办法
372
查看次数

为什么这个简单的Qt应用程序没有链接

我试着像这样编写一个简单的Qt应用程序:

main.cpp:

#include <QApplication>

class MyApp : public QApplication {
        Q_OBJECT
public:
        MyApp(int argc, char* argv[]);
};

MyApp::MyApp(int argc, char* argv[]) :
        QApplication(argc,argv) {
}

int main(int argc, char* argv[]) {
    MyApp app(argc,argv);
    return app.exec();
}
Run Code Online (Sandbox Code Playgroud)

但是当我尝试编译并将其与Qt Creator 2.3.1(Qt 4.7.4)链接时,我得到3个"未解析的外部符号"错误:

  • main.obj:-1:错误:LNK2001:未解析的外部符号
    ""public:virtual struct QMetaObject const*__thiscall MyApp :: metaObject(void)const"
    (?metaObject @ MyApp @@ UBEPBUQMetaObject @@ XZ)".

  • main.obj:-1:错误:LNK2001:未解析的外部符号
    ""public:virtual void*__thiscall MyApp :: qt_metacast(char const*)"
    (?qt_metacast @ MyApp @@ UAEPAXPBD @ Z)".

  • main.obj:-1:错误:LNK2001:未解析的外部符号
    ""public:virtual int __thiscall MyApp :: qt_metacall(enum QMetaObject :: Call,int,void**)" …

c++ qt qt4 qt-creator moc

6
推荐指数
1
解决办法
9209
查看次数

当目标在VS解决方案中失败时,如何使msbuild失败?

我在命令行上使用msbuild来构建包含C++项目的VS2012解决方案.该项目有一个在构建之后运行的目标:

<Target Name="RunTargetAfterBuild" AfterTargets="Build">
  <Error Text="I am a failing target" />
</Target>
Run Code Online (Sandbox Code Playgroud)

我希望msbuild在构建时返回错误,但是在构建过程中的某个地方,错误会丢失并且msbuild报告"构建成功".因此,ERRORLEVEL仍然设置为0,因此在自动构建期间检测是否出现问题非常困难.如何让msbuild将此错误一直传播到顶级项目/解决方案?我知道这是可能的,因为编译器错误等会发生这种情况.

以下是输出的相关部分:

> msbuild test.sln

...

...: error : I am a failing target  [...test.vcxproj]
Done Building Project "...test.vcxproj" (default targets) -- FAILED.

Done Building Project "...test.vcxproj.metaproj" (default targets).

Done Building Project "...test.sln" (Build target(s)).

Build succeeded.    --> this is NOT what I want

....

0 Warning(s)
1 Error(s)
Run Code Online (Sandbox Code Playgroud)

对于编译器错误,输出是这样的:

> msbuild test.sln

....

...: error C3861: 'HECK': identifier not found [...test.vcxproj]
Done Building Project "...test.vcxproj" (default targets) …
Run Code Online (Sandbox Code Playgroud)

msbuild projects-and-solutions visual-studio

6
推荐指数
1
解决办法
4503
查看次数

修复Windows 7上的DirectX 7延迟?

我们有一个针对DirextX 7 SDK编程的软件(即代码使用 LPDIRECTDRAWSURFACE7等)并全屏运行.主要任务是以可靠的方式在屏幕上放置一些内容以响应外部触发器.这在Windows XP上表现得非常好:通常软件会等待一些触发器,当触发时,会创建一个新帧,将其放入后备缓冲区,然后告诉DX翻转缓冲区.结果是触发器和屏幕上有效显示帧之间的近似延迟,取决于视频卡和驱动程序,对于60Hz屏幕,3帧或50毫秒.这是在各种系统上测试的,都运行NVidia卡.在一些具有较高端卡的系统上,我们甚至可以获得2帧.

但是,在Windows 7上运行相同的软件时(根本没有安装其他软件),我们不能低于5帧.在管道中的某个地方,操作系统或驱动程序或两者都需要2个额外的帧,这几乎是应用程序无法接受的.我们尝试禁用航空/桌面组合/不同的驱动程序版本/不同的视频卡但无济于事.

  • 这来自哪里?这是在某处记录的吗?
  • 有一个简单的方法来解决?我知道DirectX 7已经过时了,但升级到再次编译更新的版本可能需要大量的工作,所以另一种类型的修复会很好.也许某些可以在代码中设置的标志?

在这里编辑一些似乎相关的代码:

创建前/后表面:

ddraw7->SetCooperativeLevel( GetSafeHwnd(),
  DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWMODEX | DDSCL_MULTITHREADED )

DDSURFACEDESC2 desc;
ZeroMemory( &desc, sizeof(desc) );
desc.dwSize = sizeof( desc );
desc.dwFlags =  DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP |
                      DDSCAPS_COMPLEX | DDSCAPS_3DDEVICE |
                      DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
desc.dwBackBufferCount = 1;
ddraw7->CreateSurface( &desc, &primsurf, 0 )

DDSCAPS2 surfcaps;
ZeroMemory( &surfcaps,sizeof( surfcaps ) );
surfcaps.dwCaps = DDSCAPS_BACKBUFFER;
primsurf->GetAttachedSurface( &surfcaps, &backsurf );
Run Code Online (Sandbox Code Playgroud)

创建用于在绘制帧之前渲染帧的曲面:

DDSURFACEDESC2 desc;
ZeroMemory( …
Run Code Online (Sandbox Code Playgroud)

directx latency nvidia windows-7

6
推荐指数
1
解决办法
903
查看次数

WPF 中的屏幕截图不包含所有 UI 更新

我使用的代码这样做在WPF应用程序屏幕截图。简而言之:

var drawingvisual = new DrawingVisual();
using( DrawingContext context = drawingvisual.RenderOpen() )
{
  context.DrawRectangle( new VisualBrush( fooElement ), null, new Rect( fooElementSize ) );
  context.Close();
}
var r = new RenderTargetBitmap( ... );
r.Render( drawingvisual );
SaveBitmapToFile( r, .... );
Run Code Online (Sandbox Code Playgroud)

该原理工作得很好,例如在单击鼠标时调用时,但我在以编程方式调用它时遇到了问题。流程是:

  • 后台线程想要更​​新 UI 并使用 Application.Current.Dispatcher.Invoke
  • 后台线程做其他事情(这只需要一些毫秒)
  • 后台线程向它刚刚更新的 UI 的同一部分发出命令,再次使用 Application.Current.Dispatcher.Invoke

这在我的开发机器上工作正常,但在某些用户的机器上,这会导致保存的图像不包含所有更新。因此,例如,当 TextBlock 具有文本“running”并且上面的第一步将其设置为空字符串时,屏幕截图仍显示 TextBlock 的“running”。或者,如果第一步包括用一堆元素填充 Canvas,屏幕截图只是不包括它们。当要渲染的元素隐藏在其他窗口等后面时,情况也会变得更糟。

考虑到这一点,似乎关键问题是 WPF 使用单独的渲染线程,并且只有当该线程完成其工作时,UI 才会真正绘制并准备好捕获。四处搜索会产生一些点击,甚至一些“解决方案”围绕......

Application.Current.Dispatcher.BeginInvoke( DispatcherPriority.ApplicationIdle,
  new Action( () => { } ) ).Wait();
Run Code Online (Sandbox Code Playgroud)

...但据我所知,这只是等到 UI 线程空闲,这并不能保证渲染线程已完成更新我想要捕获的 UI 部分?无论如何,在捕获代码之前在后台线程中插入这一行没有任何区别。有时似乎有效的方法只是将后台线程阻塞 100 …

c# wpf screenshot

6
推荐指数
0
解决办法
236
查看次数